@stoplight/elements-core 8.1.3 → 8.2.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.
@@ -0,0 +1,2 @@
1
+ import { IHttpOperation } from '@stoplight/types';
2
+ export declare const xcodeSamples: IHttpOperation;
@@ -5,3 +5,6 @@ export default meta;
5
5
  export declare const Story: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, {
6
6
  data: any;
7
7
  } & import("@stoplight/react-error-boundary").ErrorBoundaryProps<{}>>;
8
+ export declare const StoryWithCustomCodeSamples: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, {
9
+ data: any;
10
+ } & import("@stoplight/react-error-boundary").ErrorBoundaryProps<{}>>;
@@ -1,7 +1,9 @@
1
1
  import { Request } from 'har-format';
2
2
  import React from 'react';
3
+ import { CodeSample } from './extractCodeSamples';
3
4
  export interface RequestSamplesProps {
4
5
  request: Request;
6
+ customCodeSamples?: CodeSample[];
5
7
  embeddedInMd?: boolean;
6
8
  }
7
9
  export declare const RequestSamples: React.NamedExoticComponent<RequestSamplesProps>;
@@ -2,3 +2,4 @@ import { RequestSamplesProps } from './RequestSamples';
2
2
  declare const _default: import("@storybook/types").ComponentAnnotations<import("@storybook/react/dist/types-0a347bb9").R, RequestSamplesProps>;
3
3
  export default _default;
4
4
  export declare const HoistedStory: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, RequestSamplesProps>;
5
+ export declare const RequestSampleWithCustomCodes: import("@storybook/types").AnnotatedStoryFn<import("@storybook/react/dist/types-0a347bb9").R, RequestSamplesProps>;
@@ -0,0 +1,7 @@
1
+ export declare type CodeSample = {
2
+ lang: string;
3
+ lib?: string;
4
+ label: string;
5
+ source: string;
6
+ };
7
+ export declare const extractCodeSamples: (obj: unknown) => CodeSample[];
@@ -1 +1,2 @@
1
+ export * from './extractCodeSamples';
1
2
  export * from './RequestSamples';
@@ -1,16 +1,14 @@
1
1
  import { CodeViewerLanguage } from '@stoplight/mosaic-code-viewer';
2
2
  import { Dictionary } from '@stoplight/types';
3
- declare type SupportedLanguage = string;
4
- declare type SupportedLibrary = string;
5
- interface LibraryConfig {
3
+ export declare type SupportedLanguage = string;
4
+ export declare type SupportedLibrary = string;
5
+ export interface LibraryConfig {
6
6
  httpSnippetLibrary: string;
7
7
  }
8
- interface LanguageConfig {
8
+ export interface LanguageConfig {
9
9
  mosaicCodeViewerLanguage: CodeViewerLanguage;
10
10
  httpSnippetLanguage: string;
11
11
  libraries?: Dictionary<LibraryConfig, SupportedLibrary>;
12
12
  }
13
- declare type RequestSampleConfigs = Dictionary<LanguageConfig, SupportedLanguage>;
13
+ export declare type RequestSampleConfigs = Dictionary<LanguageConfig, SupportedLanguage>;
14
14
  export declare const requestSampleConfigs: RequestSampleConfigs;
15
- export declare const getConfigFor: (language: string, library: string) => LanguageConfig & Partial<LibraryConfig>;
16
- export {};
package/index.esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { __rest, __awaiter } from 'tslib';
2
2
  import * as React from 'react';
3
- import React__default, { useContext, useMemo } from 'react';
3
+ import React__default, { useContext, memo, useMemo, useState, useEffect } from 'react';
4
4
  import { convertToJsonSchema } from '@stoplight/http-spec/oas';
5
5
  import { resolveInlineRef, hasRef, isPlainObject as isPlainObject$1, safeParse, safeStringify } from '@stoplight/json';
6
6
  import isArray from 'lodash/isArray.js';
@@ -17,7 +17,11 @@ import cn from 'classnames';
17
17
  import { atomWithStorage, useAtomValue } from 'jotai/utils';
18
18
  import { atom, useAtom, Provider } from 'jotai';
19
19
  import URI from 'urijs';
20
+ import isString from 'lodash/isString.js';
20
21
  import { CodeViewer } from '@stoplight/mosaic-code-viewer';
22
+ import cloneDeep from 'lodash/cloneDeep.js';
23
+ import find from 'lodash/find.js';
24
+ import findKey from 'lodash/findKey.js';
21
25
  import { isValidTargetId, HTTPSnippet } from 'httpsnippet-lite';
22
26
  import { hash } from '@stoplight/http-spec/hash';
23
27
  import capitalize from 'lodash/capitalize.js';
@@ -32,7 +36,6 @@ import keyBy from 'lodash/keyBy.js';
32
36
  import last from 'lodash/last.js';
33
37
  import map from 'lodash/map.js';
34
38
  import mapValues from 'lodash/mapValues.js';
35
- import isString from 'lodash/isString.js';
36
39
  import pickBy from 'lodash/pickBy.js';
37
40
  import { CodeEditor } from '@stoplight/mosaic-code-editor';
38
41
  import * as Sampler from '@stoplight/json-schema-sampler';
@@ -620,6 +623,29 @@ const getServerUrlWithVariableValues = (server, values) => {
620
623
  return urlString;
621
624
  };
622
625
 
626
+ const extractCodeSamples = (obj) => {
627
+ if (!isPlainObject$1(obj) || !isPlainObject$1(obj.extensions)) {
628
+ return [];
629
+ }
630
+ const codeSamples = obj.extensions['x-codeSamples'];
631
+ if (!Array.isArray(codeSamples)) {
632
+ return [];
633
+ }
634
+ return codeSamples.reduce((extracted, item) => {
635
+ if (isPlainObject$1(item) && isString(item['lang']) && isString(item['source'])) {
636
+ const lib = isString(item['lib']) ? item['lib'] : undefined;
637
+ const label = isString(item['label']) ? item['label'] : lib !== null && lib !== void 0 ? lib : item['lang'];
638
+ extracted.push({
639
+ lang: item['lang'],
640
+ lib,
641
+ label,
642
+ source: item['source'],
643
+ });
644
+ }
645
+ return extracted;
646
+ }, []);
647
+ };
648
+
623
649
  const persistAtom = (key, atomInstance) => {
624
650
  if (typeof window === 'undefined' || window.localStorage === undefined) {
625
651
  return atomInstance;
@@ -825,76 +851,149 @@ const requestSampleConfigs = {
825
851
  mosaicCodeViewerLanguage: 'swift',
826
852
  httpSnippetLanguage: 'swift',
827
853
  },
828
- };
829
- const getConfigFor = (language, library) => {
830
- var _a;
831
- const languageConfig = requestSampleConfigs[language];
832
- const libraryConfig = ((_a = languageConfig.libraries) === null || _a === void 0 ? void 0 : _a[library]) || {};
833
- return Object.assign(Object.assign({}, languageConfig), libraryConfig);
834
854
  };
835
855
 
836
- const selectedLanguageAtom = persistAtom('RequestSamples_selectedLanguage', atom('Shell'));
837
- const selectedLibraryAtom = persistAtom('RequestSamples_selectedLibrary', atom('cURL'));
856
+ const selectedLanguageAtom = persistAtom('RequestSamples_selectedLanguage', atom('shell'));
857
+ const selectedLibraryAtom = persistAtom('RequestSamples_selectedLibrary', atom('curl'));
838
858
  const fallbackText = 'Unable to generate code example';
839
- const RequestSamples = React__default.memo(({ request, embeddedInMd = false }) => {
859
+ const RequestSamples = memo(({ request, embeddedInMd = false, customCodeSamples = [] }) => {
840
860
  const [selectedLanguage, setSelectedLanguage] = useAtom(selectedLanguageAtom);
841
861
  const [selectedLibrary, setSelectedLibrary] = useAtom(selectedLibraryAtom);
842
- const { httpSnippetLanguage, httpSnippetLibrary, mosaicCodeViewerLanguage } = getConfigFor(selectedLanguage, selectedLibrary);
843
- const [requestSample, setRequestSample] = React__default.useState(null);
844
- React__default.useEffect(() => {
845
- let isStale = false;
846
- convertRequestToSample(httpSnippetLanguage, httpSnippetLibrary, request)
847
- .then(example => {
848
- if (!isStale) {
849
- setRequestSample(example);
862
+ const allRequestSamples = useMemo(() => {
863
+ var _a;
864
+ const requestSamples = cloneDeep(requestSampleConfigs);
865
+ Object.entries(requestSamples).forEach(([languageKey, value]) => {
866
+ var _a;
867
+ value.displayText = languageKey;
868
+ Object.entries(((_a = value.libraries) !== null && _a !== void 0 ? _a : (value.libraries = {}))).forEach(([libKey, value]) => {
869
+ value.displayText = `${languageKey} / ${libKey}`;
870
+ });
871
+ });
872
+ for (const customCodeSample of customCodeSamples) {
873
+ const existingLanguageSampleKey = findKey(requestSamples, {
874
+ httpSnippetLanguage: customCodeSample.lang.toLowerCase(),
875
+ });
876
+ const existingLanguageSample = requestSamples[existingLanguageSampleKey];
877
+ if (!existingLanguageSample) {
878
+ const newLanguageSample = {
879
+ displayText: customCodeSample.lang,
880
+ mosaicCodeViewerLanguage: customCodeSample.lang,
881
+ httpSnippetLanguage: customCodeSample.lang,
882
+ libraries: {},
883
+ };
884
+ if (customCodeSample.lib) {
885
+ newLanguageSample.libraries[customCodeSample.lib] = {
886
+ displayText: `${customCodeSample.lang} / ${customCodeSample.lib}`,
887
+ httpSnippetLibrary: customCodeSample.lib,
888
+ sampleCode: customCodeSample.source,
889
+ };
890
+ }
891
+ else {
892
+ newLanguageSample.sampleCode = customCodeSample.source;
893
+ }
894
+ requestSamples[customCodeSample.label] = newLanguageSample;
850
895
  }
851
- })
852
- .catch(() => {
853
- if (!isStale) {
854
- setRequestSample(fallbackText);
896
+ else {
897
+ (_a = existingLanguageSample.libraries) !== null && _a !== void 0 ? _a : (existingLanguageSample.libraries = {});
898
+ if (customCodeSample.lib) {
899
+ const existingLibrarySampleKey = findKey(existingLanguageSample.libraries, {
900
+ httpSnippetLibrary: customCodeSample.lib,
901
+ });
902
+ const existingLibrarySample = existingLanguageSample.libraries[existingLibrarySampleKey];
903
+ if (!existingLibrarySample) {
904
+ const newLibrarySample = {
905
+ displayText: `${existingLanguageSample} / ${customCodeSample.lib}`,
906
+ httpSnippetLibrary: customCodeSample.lib,
907
+ sampleCode: customCodeSample.source,
908
+ };
909
+ existingLanguageSample.libraries[customCodeSample.lib] = newLibrarySample;
910
+ }
911
+ else {
912
+ existingLibrarySample.displayText = `${existingLanguageSampleKey} / ${existingLibrarySampleKey}`;
913
+ existingLibrarySample.sampleCode = customCodeSample.source;
914
+ }
915
+ }
916
+ else {
917
+ existingLanguageSample.sampleCode = customCodeSample.source;
918
+ }
855
919
  }
856
- });
857
- return () => {
858
- isStale = true;
859
- };
860
- }, [request, httpSnippetLanguage, httpSnippetLibrary]);
861
- const menuItems = useMemo(() => {
862
- const items = Object.entries(requestSampleConfigs).map(([language, config]) => {
863
- const hasLibraries = config.libraries && Object.keys(config.libraries).length > 0;
920
+ }
921
+ return requestSamples;
922
+ }, [customCodeSamples]);
923
+ const [menuItems, selectedSampleConfig] = useMemo(() => {
924
+ var _a, _b;
925
+ const items = Object.entries(allRequestSamples).map(([languageLabel, languageConfig]) => {
926
+ var _a;
927
+ const hasLibraries = Object.keys((_a = languageConfig.libraries) !== null && _a !== void 0 ? _a : {}).length > 0;
864
928
  return {
865
- id: language,
866
- title: language,
867
- isChecked: selectedLanguage === language,
929
+ id: languageLabel,
930
+ title: languageLabel,
931
+ isChecked: selectedLanguage === languageConfig.httpSnippetLanguage,
932
+ closeOnPress: !hasLibraries,
868
933
  onPress: hasLibraries
869
934
  ? undefined
870
935
  : () => {
871
- setSelectedLanguage(language);
936
+ setSelectedLanguage(languageConfig.httpSnippetLanguage);
872
937
  setSelectedLibrary('');
873
938
  },
874
- children: config.libraries
875
- ? Object.keys(config.libraries).map(library => ({
876
- id: `${language}-${library}`,
877
- title: library,
878
- isChecked: selectedLanguage === language && selectedLibrary === library,
939
+ children: hasLibraries
940
+ ? Object.entries(languageConfig.libraries).map(([libraryLabel, libraryConfig]) => ({
941
+ id: `${languageLabel}-${libraryLabel}`,
942
+ title: libraryLabel,
943
+ isChecked: selectedLanguage === languageConfig.httpSnippetLanguage &&
944
+ selectedLibrary === libraryConfig.httpSnippetLibrary,
879
945
  onPress: () => {
880
- setSelectedLanguage(language);
881
- setSelectedLibrary(library);
946
+ setSelectedLanguage(languageConfig.httpSnippetLanguage);
947
+ setSelectedLibrary(libraryConfig.httpSnippetLibrary);
882
948
  },
883
949
  }))
884
950
  : undefined,
885
951
  };
886
952
  });
887
- return items;
888
- }, [selectedLanguage, selectedLibrary, setSelectedLanguage, setSelectedLibrary]);
953
+ const selectedLanguageSample = find(allRequestSamples, { httpSnippetLanguage: selectedLanguage });
954
+ const selectedLibrarySample = find((_a = selectedLanguageSample === null || selectedLanguageSample === void 0 ? void 0 : selectedLanguageSample.libraries) !== null && _a !== void 0 ? _a : {}, {
955
+ httpSnippetLibrary: selectedLibrary,
956
+ });
957
+ return [
958
+ items,
959
+ Object.assign(Object.assign(Object.assign({}, selectedLibrarySample), selectedLanguageSample), { displayText: (_b = selectedLibrarySample === null || selectedLibrarySample === void 0 ? void 0 : selectedLibrarySample.displayText) !== null && _b !== void 0 ? _b : selectedLanguageSample === null || selectedLanguageSample === void 0 ? void 0 : selectedLanguageSample.displayText }),
960
+ ];
961
+ }, [allRequestSamples, selectedLanguage, selectedLibrary, setSelectedLanguage, setSelectedLibrary]);
962
+ const [requestSample, setRequestSample] = useState(null);
963
+ useEffect(() => {
964
+ let isStale = false;
965
+ if (selectedSampleConfig) {
966
+ if (selectedSampleConfig.sampleCode) {
967
+ setRequestSample(selectedSampleConfig.sampleCode);
968
+ }
969
+ else {
970
+ convertRequestToSample(selectedSampleConfig.httpSnippetLanguage, selectedSampleConfig.httpSnippetLibrary, request)
971
+ .then(example => {
972
+ if (!isStale) {
973
+ setRequestSample(example);
974
+ }
975
+ })
976
+ .catch(() => {
977
+ if (!isStale) {
978
+ setRequestSample(fallbackText);
979
+ }
980
+ });
981
+ }
982
+ }
983
+ else {
984
+ setRequestSample(fallbackText);
985
+ }
986
+ return () => {
987
+ isStale = true;
988
+ };
989
+ }, [request, selectedSampleConfig]);
889
990
  return (React__default.createElement(Panel, { rounded: embeddedInMd ? undefined : true, isCollapsible: embeddedInMd },
890
991
  React__default.createElement(Panel.Titlebar, { rightComponent: React__default.createElement(CopyButton, { size: "sm", copyValue: requestSample || '' }) },
891
992
  React__default.createElement(Box, { ml: -2 },
892
993
  React__default.createElement(Menu, { "aria-label": "Request Sample Language", closeOnPress: true, items: menuItems, renderTrigger: ({ isOpen }) => (React__default.createElement(Button, { size: "sm", iconRight: "chevron-down", appearance: "minimal", active: isOpen },
893
994
  "Request Sample: ",
894
- selectedLanguage,
895
- " ",
896
- selectedLibrary ? ` / ${selectedLibrary}` : '')) }))),
897
- React__default.createElement(Panel.Content, { p: 0 }, requestSample !== null && (React__default.createElement(CodeViewer, { "aria-label": requestSample, noCopyButton: true, maxHeight: "400px", language: mosaicCodeViewerLanguage, value: requestSample, style: embeddedInMd
995
+ selectedSampleConfig.displayText)) }))),
996
+ React__default.createElement(Panel.Content, { p: 0 }, requestSample !== null && (React__default.createElement(CodeViewer, { "aria-label": requestSample, noCopyButton: true, maxHeight: "400px", language: selectedSampleConfig === null || selectedSampleConfig === void 0 ? void 0 : selectedSampleConfig.mosaicCodeViewerLanguage, value: requestSample, style: embeddedInMd
898
997
  ? undefined
899
998
  :
900
999
  {
@@ -2158,6 +2257,7 @@ const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embe
2158
2257
  const { serverVariables: serverVariableValues, updateServerVariableValue } = useServerVariables();
2159
2258
  const isMockingEnabled = mockUrl && (chosenServer === null || chosenServer === void 0 ? void 0 : chosenServer.url) === mockUrl;
2160
2259
  const hasRequiredButEmptyParameters = allParameters.some(parameter => parameter.required && !parameterValuesWithDefaults[parameter.name]);
2260
+ const customCodeSamples = extractCodeSamples(httpOperation);
2161
2261
  const getValues = () => Object.keys(bodyParameterValues)
2162
2262
  .filter(param => { var _a; return (_a = !isAllowedEmptyValues[param]) !== null && _a !== void 0 ? _a : true; })
2163
2263
  .reduce((previousValue, currentValue) => {
@@ -2287,11 +2387,11 @@ const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embe
2287
2387
  tryItPanelContents));
2288
2388
  }
2289
2389
  else {
2290
- tryItPanelElem = (React.createElement(Box, { className: "TryItPanel", bg: "canvas-100", rounded: "lg" }, tryItPanelContents));
2390
+ tryItPanelElem = (React.createElement(Box, { className: "TryItPanel", bg: "canvas-100" }, tryItPanelContents));
2291
2391
  }
2292
2392
  return (React.createElement(Box, { rounded: "lg", overflowY: "hidden" },
2293
2393
  tryItPanelElem,
2294
- requestData && embeddedInMd && React.createElement(RequestSamples, { request: requestData, embeddedInMd: true }),
2394
+ requestData && embeddedInMd && (React.createElement(RequestSamples, { request: requestData, customCodeSamples: customCodeSamples, embeddedInMd: true })),
2295
2395
  response && !('error' in response) && React.createElement(TryItResponse, { response: response }),
2296
2396
  response && 'error' in response && React.createElement(ResponseError, { state: response })));
2297
2397
  };
@@ -2335,11 +2435,12 @@ const ResponseExamples = ({ httpOperation, responseMediaType, responseStatusCode
2335
2435
  const TryItWithRequestSamples = (_a) => {
2336
2436
  var { hideTryIt } = _a, props = __rest(_a, ["hideTryIt"]);
2337
2437
  const [requestData, setRequestData] = React.useState();
2438
+ const customCodeSamples = extractCodeSamples(props.httpOperation);
2338
2439
  return (React.createElement(VStack, { spacing: 6 },
2339
2440
  !hideTryIt && (React.createElement(InvertTheme, null,
2340
2441
  React.createElement(Box, null,
2341
2442
  React.createElement(TryIt, Object.assign({}, props, { onRequestChange: setRequestData }))))),
2342
- requestData && React.createElement(RequestSamples, { request: requestData }),
2443
+ requestData && React.createElement(RequestSamples, { request: requestData, customCodeSamples: customCodeSamples }),
2343
2444
  React.createElement(ResponseExamples, Object.assign({}, props))));
2344
2445
  };
2345
2446
 
package/index.js CHANGED
@@ -19,7 +19,11 @@ var cn = require('classnames');
19
19
  var utils = require('jotai/utils');
20
20
  var jotai = require('jotai');
21
21
  var URI = require('urijs');
22
+ var isString = require('lodash/isString.js');
22
23
  var mosaicCodeViewer = require('@stoplight/mosaic-code-viewer');
24
+ var cloneDeep = require('lodash/cloneDeep.js');
25
+ var find = require('lodash/find.js');
26
+ var findKey = require('lodash/findKey.js');
23
27
  var httpsnippetLite = require('httpsnippet-lite');
24
28
  var hash = require('@stoplight/http-spec/hash');
25
29
  var capitalize = require('lodash/capitalize.js');
@@ -34,7 +38,6 @@ var keyBy = require('lodash/keyBy.js');
34
38
  var last = require('lodash/last.js');
35
39
  var map = require('lodash/map.js');
36
40
  var mapValues = require('lodash/mapValues.js');
37
- var isString = require('lodash/isString.js');
38
41
  var pickBy = require('lodash/pickBy.js');
39
42
  var mosaicCodeEditor = require('@stoplight/mosaic-code-editor');
40
43
  var Sampler = require('@stoplight/json-schema-sampler');
@@ -83,6 +86,10 @@ var isPlainObject__default = /*#__PURE__*/_interopDefaultLegacy(isPlainObject);
83
86
  var isObject__default = /*#__PURE__*/_interopDefaultLegacy(isObject);
84
87
  var cn__default = /*#__PURE__*/_interopDefaultLegacy(cn);
85
88
  var URI__default = /*#__PURE__*/_interopDefaultLegacy(URI);
89
+ var isString__default = /*#__PURE__*/_interopDefaultLegacy(isString);
90
+ var cloneDeep__default = /*#__PURE__*/_interopDefaultLegacy(cloneDeep);
91
+ var find__default = /*#__PURE__*/_interopDefaultLegacy(find);
92
+ var findKey__default = /*#__PURE__*/_interopDefaultLegacy(findKey);
86
93
  var capitalize__default = /*#__PURE__*/_interopDefaultLegacy(capitalize);
87
94
  var filter__default = /*#__PURE__*/_interopDefaultLegacy(filter);
88
95
  var flatten__default = /*#__PURE__*/_interopDefaultLegacy(flatten);
@@ -92,7 +99,6 @@ var keyBy__default = /*#__PURE__*/_interopDefaultLegacy(keyBy);
92
99
  var last__default = /*#__PURE__*/_interopDefaultLegacy(last);
93
100
  var map__default = /*#__PURE__*/_interopDefaultLegacy(map);
94
101
  var mapValues__default = /*#__PURE__*/_interopDefaultLegacy(mapValues);
95
- var isString__default = /*#__PURE__*/_interopDefaultLegacy(isString);
96
102
  var pickBy__default = /*#__PURE__*/_interopDefaultLegacy(pickBy);
97
103
  var Sampler__namespace = /*#__PURE__*/_interopNamespace(Sampler);
98
104
  var compact__default = /*#__PURE__*/_interopDefaultLegacy(compact);
@@ -677,6 +683,29 @@ const getServerUrlWithVariableValues = (server, values) => {
677
683
  return urlString;
678
684
  };
679
685
 
686
+ const extractCodeSamples = (obj) => {
687
+ if (!json.isPlainObject(obj) || !json.isPlainObject(obj.extensions)) {
688
+ return [];
689
+ }
690
+ const codeSamples = obj.extensions['x-codeSamples'];
691
+ if (!Array.isArray(codeSamples)) {
692
+ return [];
693
+ }
694
+ return codeSamples.reduce((extracted, item) => {
695
+ if (json.isPlainObject(item) && isString__default["default"](item['lang']) && isString__default["default"](item['source'])) {
696
+ const lib = isString__default["default"](item['lib']) ? item['lib'] : undefined;
697
+ const label = isString__default["default"](item['label']) ? item['label'] : lib !== null && lib !== void 0 ? lib : item['lang'];
698
+ extracted.push({
699
+ lang: item['lang'],
700
+ lib,
701
+ label,
702
+ source: item['source'],
703
+ });
704
+ }
705
+ return extracted;
706
+ }, []);
707
+ };
708
+
680
709
  const persistAtom = (key, atomInstance) => {
681
710
  if (typeof window === 'undefined' || window.localStorage === undefined) {
682
711
  return atomInstance;
@@ -882,76 +911,149 @@ const requestSampleConfigs = {
882
911
  mosaicCodeViewerLanguage: 'swift',
883
912
  httpSnippetLanguage: 'swift',
884
913
  },
885
- };
886
- const getConfigFor = (language, library) => {
887
- var _a;
888
- const languageConfig = requestSampleConfigs[language];
889
- const libraryConfig = ((_a = languageConfig.libraries) === null || _a === void 0 ? void 0 : _a[library]) || {};
890
- return Object.assign(Object.assign({}, languageConfig), libraryConfig);
891
914
  };
892
915
 
893
- const selectedLanguageAtom = persistAtom('RequestSamples_selectedLanguage', jotai.atom('Shell'));
894
- const selectedLibraryAtom = persistAtom('RequestSamples_selectedLibrary', jotai.atom('cURL'));
916
+ const selectedLanguageAtom = persistAtom('RequestSamples_selectedLanguage', jotai.atom('shell'));
917
+ const selectedLibraryAtom = persistAtom('RequestSamples_selectedLibrary', jotai.atom('curl'));
895
918
  const fallbackText = 'Unable to generate code example';
896
- const RequestSamples = React__default["default"].memo(({ request, embeddedInMd = false }) => {
919
+ const RequestSamples = React.memo(({ request, embeddedInMd = false, customCodeSamples = [] }) => {
897
920
  const [selectedLanguage, setSelectedLanguage] = jotai.useAtom(selectedLanguageAtom);
898
921
  const [selectedLibrary, setSelectedLibrary] = jotai.useAtom(selectedLibraryAtom);
899
- const { httpSnippetLanguage, httpSnippetLibrary, mosaicCodeViewerLanguage } = getConfigFor(selectedLanguage, selectedLibrary);
900
- const [requestSample, setRequestSample] = React__default["default"].useState(null);
901
- React__default["default"].useEffect(() => {
902
- let isStale = false;
903
- convertRequestToSample(httpSnippetLanguage, httpSnippetLibrary, request)
904
- .then(example => {
905
- if (!isStale) {
906
- setRequestSample(example);
922
+ const allRequestSamples = React.useMemo(() => {
923
+ var _a;
924
+ const requestSamples = cloneDeep__default["default"](requestSampleConfigs);
925
+ Object.entries(requestSamples).forEach(([languageKey, value]) => {
926
+ var _a;
927
+ value.displayText = languageKey;
928
+ Object.entries(((_a = value.libraries) !== null && _a !== void 0 ? _a : (value.libraries = {}))).forEach(([libKey, value]) => {
929
+ value.displayText = `${languageKey} / ${libKey}`;
930
+ });
931
+ });
932
+ for (const customCodeSample of customCodeSamples) {
933
+ const existingLanguageSampleKey = findKey__default["default"](requestSamples, {
934
+ httpSnippetLanguage: customCodeSample.lang.toLowerCase(),
935
+ });
936
+ const existingLanguageSample = requestSamples[existingLanguageSampleKey];
937
+ if (!existingLanguageSample) {
938
+ const newLanguageSample = {
939
+ displayText: customCodeSample.lang,
940
+ mosaicCodeViewerLanguage: customCodeSample.lang,
941
+ httpSnippetLanguage: customCodeSample.lang,
942
+ libraries: {},
943
+ };
944
+ if (customCodeSample.lib) {
945
+ newLanguageSample.libraries[customCodeSample.lib] = {
946
+ displayText: `${customCodeSample.lang} / ${customCodeSample.lib}`,
947
+ httpSnippetLibrary: customCodeSample.lib,
948
+ sampleCode: customCodeSample.source,
949
+ };
950
+ }
951
+ else {
952
+ newLanguageSample.sampleCode = customCodeSample.source;
953
+ }
954
+ requestSamples[customCodeSample.label] = newLanguageSample;
907
955
  }
908
- })
909
- .catch(() => {
910
- if (!isStale) {
911
- setRequestSample(fallbackText);
956
+ else {
957
+ (_a = existingLanguageSample.libraries) !== null && _a !== void 0 ? _a : (existingLanguageSample.libraries = {});
958
+ if (customCodeSample.lib) {
959
+ const existingLibrarySampleKey = findKey__default["default"](existingLanguageSample.libraries, {
960
+ httpSnippetLibrary: customCodeSample.lib,
961
+ });
962
+ const existingLibrarySample = existingLanguageSample.libraries[existingLibrarySampleKey];
963
+ if (!existingLibrarySample) {
964
+ const newLibrarySample = {
965
+ displayText: `${existingLanguageSample} / ${customCodeSample.lib}`,
966
+ httpSnippetLibrary: customCodeSample.lib,
967
+ sampleCode: customCodeSample.source,
968
+ };
969
+ existingLanguageSample.libraries[customCodeSample.lib] = newLibrarySample;
970
+ }
971
+ else {
972
+ existingLibrarySample.displayText = `${existingLanguageSampleKey} / ${existingLibrarySampleKey}`;
973
+ existingLibrarySample.sampleCode = customCodeSample.source;
974
+ }
975
+ }
976
+ else {
977
+ existingLanguageSample.sampleCode = customCodeSample.source;
978
+ }
912
979
  }
913
- });
914
- return () => {
915
- isStale = true;
916
- };
917
- }, [request, httpSnippetLanguage, httpSnippetLibrary]);
918
- const menuItems = React.useMemo(() => {
919
- const items = Object.entries(requestSampleConfigs).map(([language, config]) => {
920
- const hasLibraries = config.libraries && Object.keys(config.libraries).length > 0;
980
+ }
981
+ return requestSamples;
982
+ }, [customCodeSamples]);
983
+ const [menuItems, selectedSampleConfig] = React.useMemo(() => {
984
+ var _a, _b;
985
+ const items = Object.entries(allRequestSamples).map(([languageLabel, languageConfig]) => {
986
+ var _a;
987
+ const hasLibraries = Object.keys((_a = languageConfig.libraries) !== null && _a !== void 0 ? _a : {}).length > 0;
921
988
  return {
922
- id: language,
923
- title: language,
924
- isChecked: selectedLanguage === language,
989
+ id: languageLabel,
990
+ title: languageLabel,
991
+ isChecked: selectedLanguage === languageConfig.httpSnippetLanguage,
992
+ closeOnPress: !hasLibraries,
925
993
  onPress: hasLibraries
926
994
  ? undefined
927
995
  : () => {
928
- setSelectedLanguage(language);
996
+ setSelectedLanguage(languageConfig.httpSnippetLanguage);
929
997
  setSelectedLibrary('');
930
998
  },
931
- children: config.libraries
932
- ? Object.keys(config.libraries).map(library => ({
933
- id: `${language}-${library}`,
934
- title: library,
935
- isChecked: selectedLanguage === language && selectedLibrary === library,
999
+ children: hasLibraries
1000
+ ? Object.entries(languageConfig.libraries).map(([libraryLabel, libraryConfig]) => ({
1001
+ id: `${languageLabel}-${libraryLabel}`,
1002
+ title: libraryLabel,
1003
+ isChecked: selectedLanguage === languageConfig.httpSnippetLanguage &&
1004
+ selectedLibrary === libraryConfig.httpSnippetLibrary,
936
1005
  onPress: () => {
937
- setSelectedLanguage(language);
938
- setSelectedLibrary(library);
1006
+ setSelectedLanguage(languageConfig.httpSnippetLanguage);
1007
+ setSelectedLibrary(libraryConfig.httpSnippetLibrary);
939
1008
  },
940
1009
  }))
941
1010
  : undefined,
942
1011
  };
943
1012
  });
944
- return items;
945
- }, [selectedLanguage, selectedLibrary, setSelectedLanguage, setSelectedLibrary]);
1013
+ const selectedLanguageSample = find__default["default"](allRequestSamples, { httpSnippetLanguage: selectedLanguage });
1014
+ const selectedLibrarySample = find__default["default"]((_a = selectedLanguageSample === null || selectedLanguageSample === void 0 ? void 0 : selectedLanguageSample.libraries) !== null && _a !== void 0 ? _a : {}, {
1015
+ httpSnippetLibrary: selectedLibrary,
1016
+ });
1017
+ return [
1018
+ items,
1019
+ Object.assign(Object.assign(Object.assign({}, selectedLibrarySample), selectedLanguageSample), { displayText: (_b = selectedLibrarySample === null || selectedLibrarySample === void 0 ? void 0 : selectedLibrarySample.displayText) !== null && _b !== void 0 ? _b : selectedLanguageSample === null || selectedLanguageSample === void 0 ? void 0 : selectedLanguageSample.displayText }),
1020
+ ];
1021
+ }, [allRequestSamples, selectedLanguage, selectedLibrary, setSelectedLanguage, setSelectedLibrary]);
1022
+ const [requestSample, setRequestSample] = React.useState(null);
1023
+ React.useEffect(() => {
1024
+ let isStale = false;
1025
+ if (selectedSampleConfig) {
1026
+ if (selectedSampleConfig.sampleCode) {
1027
+ setRequestSample(selectedSampleConfig.sampleCode);
1028
+ }
1029
+ else {
1030
+ convertRequestToSample(selectedSampleConfig.httpSnippetLanguage, selectedSampleConfig.httpSnippetLibrary, request)
1031
+ .then(example => {
1032
+ if (!isStale) {
1033
+ setRequestSample(example);
1034
+ }
1035
+ })
1036
+ .catch(() => {
1037
+ if (!isStale) {
1038
+ setRequestSample(fallbackText);
1039
+ }
1040
+ });
1041
+ }
1042
+ }
1043
+ else {
1044
+ setRequestSample(fallbackText);
1045
+ }
1046
+ return () => {
1047
+ isStale = true;
1048
+ };
1049
+ }, [request, selectedSampleConfig]);
946
1050
  return (React__default["default"].createElement(mosaic.Panel, { rounded: embeddedInMd ? undefined : true, isCollapsible: embeddedInMd },
947
1051
  React__default["default"].createElement(mosaic.Panel.Titlebar, { rightComponent: React__default["default"].createElement(mosaic.CopyButton, { size: "sm", copyValue: requestSample || '' }) },
948
1052
  React__default["default"].createElement(mosaic.Box, { ml: -2 },
949
1053
  React__default["default"].createElement(mosaic.Menu, { "aria-label": "Request Sample Language", closeOnPress: true, items: menuItems, renderTrigger: ({ isOpen }) => (React__default["default"].createElement(mosaic.Button, { size: "sm", iconRight: "chevron-down", appearance: "minimal", active: isOpen },
950
1054
  "Request Sample: ",
951
- selectedLanguage,
952
- " ",
953
- selectedLibrary ? ` / ${selectedLibrary}` : '')) }))),
954
- React__default["default"].createElement(mosaic.Panel.Content, { p: 0 }, requestSample !== null && (React__default["default"].createElement(mosaicCodeViewer.CodeViewer, { "aria-label": requestSample, noCopyButton: true, maxHeight: "400px", language: mosaicCodeViewerLanguage, value: requestSample, style: embeddedInMd
1055
+ selectedSampleConfig.displayText)) }))),
1056
+ React__default["default"].createElement(mosaic.Panel.Content, { p: 0 }, requestSample !== null && (React__default["default"].createElement(mosaicCodeViewer.CodeViewer, { "aria-label": requestSample, noCopyButton: true, maxHeight: "400px", language: selectedSampleConfig === null || selectedSampleConfig === void 0 ? void 0 : selectedSampleConfig.mosaicCodeViewerLanguage, value: requestSample, style: embeddedInMd
955
1057
  ? undefined
956
1058
  :
957
1059
  {
@@ -2215,6 +2317,7 @@ const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embe
2215
2317
  const { serverVariables: serverVariableValues, updateServerVariableValue } = useServerVariables();
2216
2318
  const isMockingEnabled = mockUrl && (chosenServer === null || chosenServer === void 0 ? void 0 : chosenServer.url) === mockUrl;
2217
2319
  const hasRequiredButEmptyParameters = allParameters.some(parameter => parameter.required && !parameterValuesWithDefaults[parameter.name]);
2320
+ const customCodeSamples = extractCodeSamples(httpOperation);
2218
2321
  const getValues = () => Object.keys(bodyParameterValues)
2219
2322
  .filter(param => { var _a; return (_a = !isAllowedEmptyValues[param]) !== null && _a !== void 0 ? _a : true; })
2220
2323
  .reduce((previousValue, currentValue) => {
@@ -2344,11 +2447,11 @@ const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embe
2344
2447
  tryItPanelContents));
2345
2448
  }
2346
2449
  else {
2347
- tryItPanelElem = (React__namespace.createElement(mosaic.Box, { className: "TryItPanel", bg: "canvas-100", rounded: "lg" }, tryItPanelContents));
2450
+ tryItPanelElem = (React__namespace.createElement(mosaic.Box, { className: "TryItPanel", bg: "canvas-100" }, tryItPanelContents));
2348
2451
  }
2349
2452
  return (React__namespace.createElement(mosaic.Box, { rounded: "lg", overflowY: "hidden" },
2350
2453
  tryItPanelElem,
2351
- requestData && embeddedInMd && React__namespace.createElement(RequestSamples, { request: requestData, embeddedInMd: true }),
2454
+ requestData && embeddedInMd && (React__namespace.createElement(RequestSamples, { request: requestData, customCodeSamples: customCodeSamples, embeddedInMd: true })),
2352
2455
  response && !('error' in response) && React__namespace.createElement(TryItResponse, { response: response }),
2353
2456
  response && 'error' in response && React__namespace.createElement(ResponseError, { state: response })));
2354
2457
  };
@@ -2392,11 +2495,12 @@ const ResponseExamples = ({ httpOperation, responseMediaType, responseStatusCode
2392
2495
  const TryItWithRequestSamples = (_a) => {
2393
2496
  var { hideTryIt } = _a, props = tslib.__rest(_a, ["hideTryIt"]);
2394
2497
  const [requestData, setRequestData] = React__namespace.useState();
2498
+ const customCodeSamples = extractCodeSamples(props.httpOperation);
2395
2499
  return (React__namespace.createElement(mosaic.VStack, { spacing: 6 },
2396
2500
  !hideTryIt && (React__namespace.createElement(mosaic.InvertTheme, null,
2397
2501
  React__namespace.createElement(mosaic.Box, null,
2398
2502
  React__namespace.createElement(TryIt, Object.assign({}, props, { onRequestChange: setRequestData }))))),
2399
- requestData && React__namespace.createElement(RequestSamples, { request: requestData }),
2503
+ requestData && React__namespace.createElement(RequestSamples, { request: requestData, customCodeSamples: customCodeSamples }),
2400
2504
  React__namespace.createElement(ResponseExamples, Object.assign({}, props))));
2401
2505
  };
2402
2506
 
package/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { __rest, __awaiter } from 'tslib';
2
2
  import * as React from 'react';
3
- import React__default, { useContext, useMemo } from 'react';
3
+ import React__default, { useContext, memo, useMemo, useState, useEffect } from 'react';
4
4
  import { convertToJsonSchema } from '@stoplight/http-spec/oas';
5
5
  import { resolveInlineRef, hasRef, isPlainObject as isPlainObject$1, safeParse, safeStringify } from '@stoplight/json';
6
6
  import isArray from 'lodash/isArray.js';
@@ -17,7 +17,11 @@ import cn from 'classnames';
17
17
  import { atomWithStorage, useAtomValue } from 'jotai/utils';
18
18
  import { atom, useAtom, Provider } from 'jotai';
19
19
  import URI from 'urijs';
20
+ import isString from 'lodash/isString.js';
20
21
  import { CodeViewer } from '@stoplight/mosaic-code-viewer';
22
+ import cloneDeep from 'lodash/cloneDeep.js';
23
+ import find from 'lodash/find.js';
24
+ import findKey from 'lodash/findKey.js';
21
25
  import { isValidTargetId, HTTPSnippet } from 'httpsnippet-lite';
22
26
  import { hash } from '@stoplight/http-spec/hash';
23
27
  import capitalize from 'lodash/capitalize.js';
@@ -32,7 +36,6 @@ import keyBy from 'lodash/keyBy.js';
32
36
  import last from 'lodash/last.js';
33
37
  import map from 'lodash/map.js';
34
38
  import mapValues from 'lodash/mapValues.js';
35
- import isString from 'lodash/isString.js';
36
39
  import pickBy from 'lodash/pickBy.js';
37
40
  import { CodeEditor } from '@stoplight/mosaic-code-editor';
38
41
  import * as Sampler from '@stoplight/json-schema-sampler';
@@ -620,6 +623,29 @@ const getServerUrlWithVariableValues = (server, values) => {
620
623
  return urlString;
621
624
  };
622
625
 
626
+ const extractCodeSamples = (obj) => {
627
+ if (!isPlainObject$1(obj) || !isPlainObject$1(obj.extensions)) {
628
+ return [];
629
+ }
630
+ const codeSamples = obj.extensions['x-codeSamples'];
631
+ if (!Array.isArray(codeSamples)) {
632
+ return [];
633
+ }
634
+ return codeSamples.reduce((extracted, item) => {
635
+ if (isPlainObject$1(item) && isString(item['lang']) && isString(item['source'])) {
636
+ const lib = isString(item['lib']) ? item['lib'] : undefined;
637
+ const label = isString(item['label']) ? item['label'] : lib !== null && lib !== void 0 ? lib : item['lang'];
638
+ extracted.push({
639
+ lang: item['lang'],
640
+ lib,
641
+ label,
642
+ source: item['source'],
643
+ });
644
+ }
645
+ return extracted;
646
+ }, []);
647
+ };
648
+
623
649
  const persistAtom = (key, atomInstance) => {
624
650
  if (typeof window === 'undefined' || window.localStorage === undefined) {
625
651
  return atomInstance;
@@ -825,76 +851,149 @@ const requestSampleConfigs = {
825
851
  mosaicCodeViewerLanguage: 'swift',
826
852
  httpSnippetLanguage: 'swift',
827
853
  },
828
- };
829
- const getConfigFor = (language, library) => {
830
- var _a;
831
- const languageConfig = requestSampleConfigs[language];
832
- const libraryConfig = ((_a = languageConfig.libraries) === null || _a === void 0 ? void 0 : _a[library]) || {};
833
- return Object.assign(Object.assign({}, languageConfig), libraryConfig);
834
854
  };
835
855
 
836
- const selectedLanguageAtom = persistAtom('RequestSamples_selectedLanguage', atom('Shell'));
837
- const selectedLibraryAtom = persistAtom('RequestSamples_selectedLibrary', atom('cURL'));
856
+ const selectedLanguageAtom = persistAtom('RequestSamples_selectedLanguage', atom('shell'));
857
+ const selectedLibraryAtom = persistAtom('RequestSamples_selectedLibrary', atom('curl'));
838
858
  const fallbackText = 'Unable to generate code example';
839
- const RequestSamples = React__default.memo(({ request, embeddedInMd = false }) => {
859
+ const RequestSamples = memo(({ request, embeddedInMd = false, customCodeSamples = [] }) => {
840
860
  const [selectedLanguage, setSelectedLanguage] = useAtom(selectedLanguageAtom);
841
861
  const [selectedLibrary, setSelectedLibrary] = useAtom(selectedLibraryAtom);
842
- const { httpSnippetLanguage, httpSnippetLibrary, mosaicCodeViewerLanguage } = getConfigFor(selectedLanguage, selectedLibrary);
843
- const [requestSample, setRequestSample] = React__default.useState(null);
844
- React__default.useEffect(() => {
845
- let isStale = false;
846
- convertRequestToSample(httpSnippetLanguage, httpSnippetLibrary, request)
847
- .then(example => {
848
- if (!isStale) {
849
- setRequestSample(example);
862
+ const allRequestSamples = useMemo(() => {
863
+ var _a;
864
+ const requestSamples = cloneDeep(requestSampleConfigs);
865
+ Object.entries(requestSamples).forEach(([languageKey, value]) => {
866
+ var _a;
867
+ value.displayText = languageKey;
868
+ Object.entries(((_a = value.libraries) !== null && _a !== void 0 ? _a : (value.libraries = {}))).forEach(([libKey, value]) => {
869
+ value.displayText = `${languageKey} / ${libKey}`;
870
+ });
871
+ });
872
+ for (const customCodeSample of customCodeSamples) {
873
+ const existingLanguageSampleKey = findKey(requestSamples, {
874
+ httpSnippetLanguage: customCodeSample.lang.toLowerCase(),
875
+ });
876
+ const existingLanguageSample = requestSamples[existingLanguageSampleKey];
877
+ if (!existingLanguageSample) {
878
+ const newLanguageSample = {
879
+ displayText: customCodeSample.lang,
880
+ mosaicCodeViewerLanguage: customCodeSample.lang,
881
+ httpSnippetLanguage: customCodeSample.lang,
882
+ libraries: {},
883
+ };
884
+ if (customCodeSample.lib) {
885
+ newLanguageSample.libraries[customCodeSample.lib] = {
886
+ displayText: `${customCodeSample.lang} / ${customCodeSample.lib}`,
887
+ httpSnippetLibrary: customCodeSample.lib,
888
+ sampleCode: customCodeSample.source,
889
+ };
890
+ }
891
+ else {
892
+ newLanguageSample.sampleCode = customCodeSample.source;
893
+ }
894
+ requestSamples[customCodeSample.label] = newLanguageSample;
850
895
  }
851
- })
852
- .catch(() => {
853
- if (!isStale) {
854
- setRequestSample(fallbackText);
896
+ else {
897
+ (_a = existingLanguageSample.libraries) !== null && _a !== void 0 ? _a : (existingLanguageSample.libraries = {});
898
+ if (customCodeSample.lib) {
899
+ const existingLibrarySampleKey = findKey(existingLanguageSample.libraries, {
900
+ httpSnippetLibrary: customCodeSample.lib,
901
+ });
902
+ const existingLibrarySample = existingLanguageSample.libraries[existingLibrarySampleKey];
903
+ if (!existingLibrarySample) {
904
+ const newLibrarySample = {
905
+ displayText: `${existingLanguageSample} / ${customCodeSample.lib}`,
906
+ httpSnippetLibrary: customCodeSample.lib,
907
+ sampleCode: customCodeSample.source,
908
+ };
909
+ existingLanguageSample.libraries[customCodeSample.lib] = newLibrarySample;
910
+ }
911
+ else {
912
+ existingLibrarySample.displayText = `${existingLanguageSampleKey} / ${existingLibrarySampleKey}`;
913
+ existingLibrarySample.sampleCode = customCodeSample.source;
914
+ }
915
+ }
916
+ else {
917
+ existingLanguageSample.sampleCode = customCodeSample.source;
918
+ }
855
919
  }
856
- });
857
- return () => {
858
- isStale = true;
859
- };
860
- }, [request, httpSnippetLanguage, httpSnippetLibrary]);
861
- const menuItems = useMemo(() => {
862
- const items = Object.entries(requestSampleConfigs).map(([language, config]) => {
863
- const hasLibraries = config.libraries && Object.keys(config.libraries).length > 0;
920
+ }
921
+ return requestSamples;
922
+ }, [customCodeSamples]);
923
+ const [menuItems, selectedSampleConfig] = useMemo(() => {
924
+ var _a, _b;
925
+ const items = Object.entries(allRequestSamples).map(([languageLabel, languageConfig]) => {
926
+ var _a;
927
+ const hasLibraries = Object.keys((_a = languageConfig.libraries) !== null && _a !== void 0 ? _a : {}).length > 0;
864
928
  return {
865
- id: language,
866
- title: language,
867
- isChecked: selectedLanguage === language,
929
+ id: languageLabel,
930
+ title: languageLabel,
931
+ isChecked: selectedLanguage === languageConfig.httpSnippetLanguage,
932
+ closeOnPress: !hasLibraries,
868
933
  onPress: hasLibraries
869
934
  ? undefined
870
935
  : () => {
871
- setSelectedLanguage(language);
936
+ setSelectedLanguage(languageConfig.httpSnippetLanguage);
872
937
  setSelectedLibrary('');
873
938
  },
874
- children: config.libraries
875
- ? Object.keys(config.libraries).map(library => ({
876
- id: `${language}-${library}`,
877
- title: library,
878
- isChecked: selectedLanguage === language && selectedLibrary === library,
939
+ children: hasLibraries
940
+ ? Object.entries(languageConfig.libraries).map(([libraryLabel, libraryConfig]) => ({
941
+ id: `${languageLabel}-${libraryLabel}`,
942
+ title: libraryLabel,
943
+ isChecked: selectedLanguage === languageConfig.httpSnippetLanguage &&
944
+ selectedLibrary === libraryConfig.httpSnippetLibrary,
879
945
  onPress: () => {
880
- setSelectedLanguage(language);
881
- setSelectedLibrary(library);
946
+ setSelectedLanguage(languageConfig.httpSnippetLanguage);
947
+ setSelectedLibrary(libraryConfig.httpSnippetLibrary);
882
948
  },
883
949
  }))
884
950
  : undefined,
885
951
  };
886
952
  });
887
- return items;
888
- }, [selectedLanguage, selectedLibrary, setSelectedLanguage, setSelectedLibrary]);
953
+ const selectedLanguageSample = find(allRequestSamples, { httpSnippetLanguage: selectedLanguage });
954
+ const selectedLibrarySample = find((_a = selectedLanguageSample === null || selectedLanguageSample === void 0 ? void 0 : selectedLanguageSample.libraries) !== null && _a !== void 0 ? _a : {}, {
955
+ httpSnippetLibrary: selectedLibrary,
956
+ });
957
+ return [
958
+ items,
959
+ Object.assign(Object.assign(Object.assign({}, selectedLibrarySample), selectedLanguageSample), { displayText: (_b = selectedLibrarySample === null || selectedLibrarySample === void 0 ? void 0 : selectedLibrarySample.displayText) !== null && _b !== void 0 ? _b : selectedLanguageSample === null || selectedLanguageSample === void 0 ? void 0 : selectedLanguageSample.displayText }),
960
+ ];
961
+ }, [allRequestSamples, selectedLanguage, selectedLibrary, setSelectedLanguage, setSelectedLibrary]);
962
+ const [requestSample, setRequestSample] = useState(null);
963
+ useEffect(() => {
964
+ let isStale = false;
965
+ if (selectedSampleConfig) {
966
+ if (selectedSampleConfig.sampleCode) {
967
+ setRequestSample(selectedSampleConfig.sampleCode);
968
+ }
969
+ else {
970
+ convertRequestToSample(selectedSampleConfig.httpSnippetLanguage, selectedSampleConfig.httpSnippetLibrary, request)
971
+ .then(example => {
972
+ if (!isStale) {
973
+ setRequestSample(example);
974
+ }
975
+ })
976
+ .catch(() => {
977
+ if (!isStale) {
978
+ setRequestSample(fallbackText);
979
+ }
980
+ });
981
+ }
982
+ }
983
+ else {
984
+ setRequestSample(fallbackText);
985
+ }
986
+ return () => {
987
+ isStale = true;
988
+ };
989
+ }, [request, selectedSampleConfig]);
889
990
  return (React__default.createElement(Panel, { rounded: embeddedInMd ? undefined : true, isCollapsible: embeddedInMd },
890
991
  React__default.createElement(Panel.Titlebar, { rightComponent: React__default.createElement(CopyButton, { size: "sm", copyValue: requestSample || '' }) },
891
992
  React__default.createElement(Box, { ml: -2 },
892
993
  React__default.createElement(Menu, { "aria-label": "Request Sample Language", closeOnPress: true, items: menuItems, renderTrigger: ({ isOpen }) => (React__default.createElement(Button, { size: "sm", iconRight: "chevron-down", appearance: "minimal", active: isOpen },
893
994
  "Request Sample: ",
894
- selectedLanguage,
895
- " ",
896
- selectedLibrary ? ` / ${selectedLibrary}` : '')) }))),
897
- React__default.createElement(Panel.Content, { p: 0 }, requestSample !== null && (React__default.createElement(CodeViewer, { "aria-label": requestSample, noCopyButton: true, maxHeight: "400px", language: mosaicCodeViewerLanguage, value: requestSample, style: embeddedInMd
995
+ selectedSampleConfig.displayText)) }))),
996
+ React__default.createElement(Panel.Content, { p: 0 }, requestSample !== null && (React__default.createElement(CodeViewer, { "aria-label": requestSample, noCopyButton: true, maxHeight: "400px", language: selectedSampleConfig === null || selectedSampleConfig === void 0 ? void 0 : selectedSampleConfig.mosaicCodeViewerLanguage, value: requestSample, style: embeddedInMd
898
997
  ? undefined
899
998
  :
900
999
  {
@@ -2158,6 +2257,7 @@ const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embe
2158
2257
  const { serverVariables: serverVariableValues, updateServerVariableValue } = useServerVariables();
2159
2258
  const isMockingEnabled = mockUrl && (chosenServer === null || chosenServer === void 0 ? void 0 : chosenServer.url) === mockUrl;
2160
2259
  const hasRequiredButEmptyParameters = allParameters.some(parameter => parameter.required && !parameterValuesWithDefaults[parameter.name]);
2260
+ const customCodeSamples = extractCodeSamples(httpOperation);
2161
2261
  const getValues = () => Object.keys(bodyParameterValues)
2162
2262
  .filter(param => { var _a; return (_a = !isAllowedEmptyValues[param]) !== null && _a !== void 0 ? _a : true; })
2163
2263
  .reduce((previousValue, currentValue) => {
@@ -2287,11 +2387,11 @@ const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embe
2287
2387
  tryItPanelContents));
2288
2388
  }
2289
2389
  else {
2290
- tryItPanelElem = (React.createElement(Box, { className: "TryItPanel", bg: "canvas-100", rounded: "lg" }, tryItPanelContents));
2390
+ tryItPanelElem = (React.createElement(Box, { className: "TryItPanel", bg: "canvas-100" }, tryItPanelContents));
2291
2391
  }
2292
2392
  return (React.createElement(Box, { rounded: "lg", overflowY: "hidden" },
2293
2393
  tryItPanelElem,
2294
- requestData && embeddedInMd && React.createElement(RequestSamples, { request: requestData, embeddedInMd: true }),
2394
+ requestData && embeddedInMd && (React.createElement(RequestSamples, { request: requestData, customCodeSamples: customCodeSamples, embeddedInMd: true })),
2295
2395
  response && !('error' in response) && React.createElement(TryItResponse, { response: response }),
2296
2396
  response && 'error' in response && React.createElement(ResponseError, { state: response })));
2297
2397
  };
@@ -2335,11 +2435,12 @@ const ResponseExamples = ({ httpOperation, responseMediaType, responseStatusCode
2335
2435
  const TryItWithRequestSamples = (_a) => {
2336
2436
  var { hideTryIt } = _a, props = __rest(_a, ["hideTryIt"]);
2337
2437
  const [requestData, setRequestData] = React.useState();
2438
+ const customCodeSamples = extractCodeSamples(props.httpOperation);
2338
2439
  return (React.createElement(VStack, { spacing: 6 },
2339
2440
  !hideTryIt && (React.createElement(InvertTheme, null,
2340
2441
  React.createElement(Box, null,
2341
2442
  React.createElement(TryIt, Object.assign({}, props, { onRequestChange: setRequestData }))))),
2342
- requestData && React.createElement(RequestSamples, { request: requestData }),
2443
+ requestData && React.createElement(RequestSamples, { request: requestData, customCodeSamples: customCodeSamples }),
2343
2444
  React.createElement(ResponseExamples, Object.assign({}, props))));
2344
2445
  };
2345
2446
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stoplight/elements-core",
3
- "version": "8.1.3",
3
+ "version": "8.2.0",
4
4
  "main": "./index.js",
5
5
  "sideEffects": [
6
6
  "web-components.min.js",
@@ -29,7 +29,7 @@
29
29
  "@stoplight/json-schema-ref-parser": "^9.0.5",
30
30
  "@stoplight/json-schema-sampler": "0.2.3",
31
31
  "@stoplight/json-schema-tree": "^4.0.0",
32
- "@stoplight/json-schema-viewer": "^4.15.1",
32
+ "@stoplight/json-schema-viewer": "4.16.1",
33
33
  "@stoplight/markdown-viewer": "^5.7.0",
34
34
  "@stoplight/mosaic": "^1.53.1",
35
35
  "@stoplight/mosaic-code-editor": "^1.53.1",