@stoplight/elements-core 8.1.4 → 8.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.mjs CHANGED
@@ -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';
@@ -41,6 +44,7 @@ import uniq from 'lodash/uniq.js';
41
44
  import orderBy from 'lodash/orderBy.js';
42
45
  import uniqBy from 'lodash/uniqBy.js';
43
46
  import formatXml from 'xml-formatter';
47
+ import memoize from 'lodash/memoize.js';
44
48
  import entries from 'lodash/entries.js';
45
49
  import keys from 'lodash/keys.js';
46
50
  import sortBy from 'lodash/sortBy.js';
@@ -161,8 +165,8 @@ const ElementsOptionsContext = React.createContext(DEFAULT_CONTEXT);
161
165
  const useOptionsCtx = () => {
162
166
  return React.useContext(ElementsOptionsContext) || DEFAULT_CONTEXT;
163
167
  };
164
- function ElementsOptionsProvider({ children, nodeHasChanged }) {
165
- return (React.createElement(ElementsOptionsContext.Provider, { value: Object.assign({}, DEFAULT_CONTEXT, { nodeHasChanged }) }, children));
168
+ function ElementsOptionsProvider({ children, nodeHasChanged, renderExtensionAddon }) {
169
+ return (React.createElement(ElementsOptionsContext.Provider, { value: Object.assign({}, DEFAULT_CONTEXT, { nodeHasChanged, renderExtensionAddon }) }, children));
166
170
  }
167
171
 
168
172
  function isSMDASTRoot(maybeAst) {
@@ -447,6 +451,9 @@ const HttpMethodColors = {
447
451
  put: 'warning',
448
452
  patch: 'warning',
449
453
  delete: 'danger',
454
+ head: '#9061F9',
455
+ options: '#0D5AA7',
456
+ trace: '#0D0B28',
450
457
  };
451
458
  const HttpCodeColor = {
452
459
  0: 'red',
@@ -620,6 +627,29 @@ const getServerUrlWithVariableValues = (server, values) => {
620
627
  return urlString;
621
628
  };
622
629
 
630
+ const extractCodeSamples = (obj) => {
631
+ if (!isPlainObject$1(obj) || !isPlainObject$1(obj.extensions)) {
632
+ return [];
633
+ }
634
+ const codeSamples = obj.extensions['x-codeSamples'];
635
+ if (!Array.isArray(codeSamples)) {
636
+ return [];
637
+ }
638
+ return codeSamples.reduce((extracted, item) => {
639
+ if (isPlainObject$1(item) && isString(item['lang']) && isString(item['source'])) {
640
+ const lib = isString(item['lib']) ? item['lib'] : undefined;
641
+ const label = isString(item['label']) ? item['label'] : lib !== null && lib !== void 0 ? lib : item['lang'];
642
+ extracted.push({
643
+ lang: item['lang'],
644
+ lib,
645
+ label,
646
+ source: item['source'],
647
+ });
648
+ }
649
+ return extracted;
650
+ }, []);
651
+ };
652
+
623
653
  const persistAtom = (key, atomInstance) => {
624
654
  if (typeof window === 'undefined' || window.localStorage === undefined) {
625
655
  return atomInstance;
@@ -825,76 +855,149 @@ const requestSampleConfigs = {
825
855
  mosaicCodeViewerLanguage: 'swift',
826
856
  httpSnippetLanguage: 'swift',
827
857
  },
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
858
  };
835
859
 
836
- const selectedLanguageAtom = persistAtom('RequestSamples_selectedLanguage', atom('Shell'));
837
- const selectedLibraryAtom = persistAtom('RequestSamples_selectedLibrary', atom('cURL'));
860
+ const selectedLanguageAtom = persistAtom('RequestSamples_selectedLanguage', atom('shell'));
861
+ const selectedLibraryAtom = persistAtom('RequestSamples_selectedLibrary', atom('curl'));
838
862
  const fallbackText = 'Unable to generate code example';
839
- const RequestSamples = React__default.memo(({ request, embeddedInMd = false }) => {
863
+ const RequestSamples = memo(({ request, embeddedInMd = false, customCodeSamples = [] }) => {
840
864
  const [selectedLanguage, setSelectedLanguage] = useAtom(selectedLanguageAtom);
841
865
  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);
866
+ const allRequestSamples = useMemo(() => {
867
+ var _a;
868
+ const requestSamples = cloneDeep(requestSampleConfigs);
869
+ Object.entries(requestSamples).forEach(([languageKey, value]) => {
870
+ var _a;
871
+ value.displayText = languageKey;
872
+ Object.entries(((_a = value.libraries) !== null && _a !== void 0 ? _a : (value.libraries = {}))).forEach(([libKey, value]) => {
873
+ value.displayText = `${languageKey} / ${libKey}`;
874
+ });
875
+ });
876
+ for (const customCodeSample of customCodeSamples) {
877
+ const existingLanguageSampleKey = findKey(requestSamples, {
878
+ httpSnippetLanguage: customCodeSample.lang.toLowerCase(),
879
+ });
880
+ const existingLanguageSample = requestSamples[existingLanguageSampleKey];
881
+ if (!existingLanguageSample) {
882
+ const newLanguageSample = {
883
+ displayText: customCodeSample.lang,
884
+ mosaicCodeViewerLanguage: customCodeSample.lang,
885
+ httpSnippetLanguage: customCodeSample.lang,
886
+ libraries: {},
887
+ };
888
+ if (customCodeSample.lib) {
889
+ newLanguageSample.libraries[customCodeSample.lib] = {
890
+ displayText: `${customCodeSample.lang} / ${customCodeSample.lib}`,
891
+ httpSnippetLibrary: customCodeSample.lib,
892
+ sampleCode: customCodeSample.source,
893
+ };
894
+ }
895
+ else {
896
+ newLanguageSample.sampleCode = customCodeSample.source;
897
+ }
898
+ requestSamples[customCodeSample.label] = newLanguageSample;
850
899
  }
851
- })
852
- .catch(() => {
853
- if (!isStale) {
854
- setRequestSample(fallbackText);
900
+ else {
901
+ (_a = existingLanguageSample.libraries) !== null && _a !== void 0 ? _a : (existingLanguageSample.libraries = {});
902
+ if (customCodeSample.lib) {
903
+ const existingLibrarySampleKey = findKey(existingLanguageSample.libraries, {
904
+ httpSnippetLibrary: customCodeSample.lib,
905
+ });
906
+ const existingLibrarySample = existingLanguageSample.libraries[existingLibrarySampleKey];
907
+ if (!existingLibrarySample) {
908
+ const newLibrarySample = {
909
+ displayText: `${existingLanguageSample} / ${customCodeSample.lib}`,
910
+ httpSnippetLibrary: customCodeSample.lib,
911
+ sampleCode: customCodeSample.source,
912
+ };
913
+ existingLanguageSample.libraries[customCodeSample.lib] = newLibrarySample;
914
+ }
915
+ else {
916
+ existingLibrarySample.displayText = `${existingLanguageSampleKey} / ${existingLibrarySampleKey}`;
917
+ existingLibrarySample.sampleCode = customCodeSample.source;
918
+ }
919
+ }
920
+ else {
921
+ existingLanguageSample.sampleCode = customCodeSample.source;
922
+ }
855
923
  }
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;
924
+ }
925
+ return requestSamples;
926
+ }, [customCodeSamples]);
927
+ const [menuItems, selectedSampleConfig] = useMemo(() => {
928
+ var _a, _b;
929
+ const items = Object.entries(allRequestSamples).map(([languageLabel, languageConfig]) => {
930
+ var _a;
931
+ const hasLibraries = Object.keys((_a = languageConfig.libraries) !== null && _a !== void 0 ? _a : {}).length > 0;
864
932
  return {
865
- id: language,
866
- title: language,
867
- isChecked: selectedLanguage === language,
933
+ id: languageLabel,
934
+ title: languageLabel,
935
+ isChecked: selectedLanguage === languageConfig.httpSnippetLanguage,
936
+ closeOnPress: !hasLibraries,
868
937
  onPress: hasLibraries
869
938
  ? undefined
870
939
  : () => {
871
- setSelectedLanguage(language);
940
+ setSelectedLanguage(languageConfig.httpSnippetLanguage);
872
941
  setSelectedLibrary('');
873
942
  },
874
- children: config.libraries
875
- ? Object.keys(config.libraries).map(library => ({
876
- id: `${language}-${library}`,
877
- title: library,
878
- isChecked: selectedLanguage === language && selectedLibrary === library,
943
+ children: hasLibraries
944
+ ? Object.entries(languageConfig.libraries).map(([libraryLabel, libraryConfig]) => ({
945
+ id: `${languageLabel}-${libraryLabel}`,
946
+ title: libraryLabel,
947
+ isChecked: selectedLanguage === languageConfig.httpSnippetLanguage &&
948
+ selectedLibrary === libraryConfig.httpSnippetLibrary,
879
949
  onPress: () => {
880
- setSelectedLanguage(language);
881
- setSelectedLibrary(library);
950
+ setSelectedLanguage(languageConfig.httpSnippetLanguage);
951
+ setSelectedLibrary(libraryConfig.httpSnippetLibrary);
882
952
  },
883
953
  }))
884
954
  : undefined,
885
955
  };
886
956
  });
887
- return items;
888
- }, [selectedLanguage, selectedLibrary, setSelectedLanguage, setSelectedLibrary]);
957
+ const selectedLanguageSample = find(allRequestSamples, { httpSnippetLanguage: selectedLanguage });
958
+ const selectedLibrarySample = find((_a = selectedLanguageSample === null || selectedLanguageSample === void 0 ? void 0 : selectedLanguageSample.libraries) !== null && _a !== void 0 ? _a : {}, {
959
+ httpSnippetLibrary: selectedLibrary,
960
+ });
961
+ return [
962
+ items,
963
+ 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 }),
964
+ ];
965
+ }, [allRequestSamples, selectedLanguage, selectedLibrary, setSelectedLanguage, setSelectedLibrary]);
966
+ const [requestSample, setRequestSample] = useState(null);
967
+ useEffect(() => {
968
+ let isStale = false;
969
+ if (selectedSampleConfig) {
970
+ if (selectedSampleConfig.sampleCode) {
971
+ setRequestSample(selectedSampleConfig.sampleCode);
972
+ }
973
+ else {
974
+ convertRequestToSample(selectedSampleConfig.httpSnippetLanguage, selectedSampleConfig.httpSnippetLibrary, request)
975
+ .then(example => {
976
+ if (!isStale) {
977
+ setRequestSample(example);
978
+ }
979
+ })
980
+ .catch(() => {
981
+ if (!isStale) {
982
+ setRequestSample(fallbackText);
983
+ }
984
+ });
985
+ }
986
+ }
987
+ else {
988
+ setRequestSample(fallbackText);
989
+ }
990
+ return () => {
991
+ isStale = true;
992
+ };
993
+ }, [request, selectedSampleConfig]);
889
994
  return (React__default.createElement(Panel, { rounded: embeddedInMd ? undefined : true, isCollapsible: embeddedInMd },
890
995
  React__default.createElement(Panel.Titlebar, { rightComponent: React__default.createElement(CopyButton, { size: "sm", copyValue: requestSample || '' }) },
891
996
  React__default.createElement(Box, { ml: -2 },
892
997
  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
998
  "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
999
+ selectedSampleConfig.displayText)) }))),
1000
+ 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
1001
  ? undefined
899
1002
  :
900
1003
  {
@@ -2158,6 +2261,7 @@ const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embe
2158
2261
  const { serverVariables: serverVariableValues, updateServerVariableValue } = useServerVariables();
2159
2262
  const isMockingEnabled = mockUrl && (chosenServer === null || chosenServer === void 0 ? void 0 : chosenServer.url) === mockUrl;
2160
2263
  const hasRequiredButEmptyParameters = allParameters.some(parameter => parameter.required && !parameterValuesWithDefaults[parameter.name]);
2264
+ const customCodeSamples = extractCodeSamples(httpOperation);
2161
2265
  const getValues = () => Object.keys(bodyParameterValues)
2162
2266
  .filter(param => { var _a; return (_a = !isAllowedEmptyValues[param]) !== null && _a !== void 0 ? _a : true; })
2163
2267
  .reduce((previousValue, currentValue) => {
@@ -2287,11 +2391,11 @@ const TryIt = ({ httpOperation, mockUrl, onRequestChange, requestBodyIndex, embe
2287
2391
  tryItPanelContents));
2288
2392
  }
2289
2393
  else {
2290
- tryItPanelElem = (React.createElement(Box, { className: "TryItPanel", bg: "canvas-100", rounded: "lg" }, tryItPanelContents));
2394
+ tryItPanelElem = (React.createElement(Box, { className: "TryItPanel", bg: "canvas-100" }, tryItPanelContents));
2291
2395
  }
2292
2396
  return (React.createElement(Box, { rounded: "lg", overflowY: "hidden" },
2293
2397
  tryItPanelElem,
2294
- requestData && embeddedInMd && React.createElement(RequestSamples, { request: requestData, embeddedInMd: true }),
2398
+ requestData && embeddedInMd && (React.createElement(RequestSamples, { request: requestData, customCodeSamples: customCodeSamples, embeddedInMd: true })),
2295
2399
  response && !('error' in response) && React.createElement(TryItResponse, { response: response }),
2296
2400
  response && 'error' in response && React.createElement(ResponseError, { state: response })));
2297
2401
  };
@@ -2335,14 +2439,41 @@ const ResponseExamples = ({ httpOperation, responseMediaType, responseStatusCode
2335
2439
  const TryItWithRequestSamples = (_a) => {
2336
2440
  var { hideTryIt } = _a, props = __rest(_a, ["hideTryIt"]);
2337
2441
  const [requestData, setRequestData] = React.useState();
2442
+ const customCodeSamples = extractCodeSamples(props.httpOperation);
2338
2443
  return (React.createElement(VStack, { spacing: 6 },
2339
2444
  !hideTryIt && (React.createElement(InvertTheme, null,
2340
2445
  React.createElement(Box, null,
2341
2446
  React.createElement(TryIt, Object.assign({}, props, { onRequestChange: setRequestData }))))),
2342
- requestData && React.createElement(RequestSamples, { request: requestData }),
2447
+ requestData && React.createElement(RequestSamples, { request: requestData, customCodeSamples: customCodeSamples }),
2343
2448
  React.createElement(ResponseExamples, Object.assign({}, props))));
2344
2449
  };
2345
2450
 
2451
+ const getVendorExtensions = memoize((data) => {
2452
+ const vendorExtensionNames = Object.keys(data).filter(item => item.startsWith('x-'));
2453
+ const vendorExtensions = vendorExtensionNames.reduce((previousValue, currentValue, currentIndex) => {
2454
+ return Object.assign(Object.assign({}, previousValue), { [currentValue]: data[currentValue] });
2455
+ }, {});
2456
+ return vendorExtensions;
2457
+ });
2458
+ const NodeVendorExtensions = React.memo(({ data }) => {
2459
+ const { renderExtensionAddon } = useOptionsCtx();
2460
+ if (!renderExtensionAddon) {
2461
+ return null;
2462
+ }
2463
+ const originalObject = getOriginalObject(data);
2464
+ const vendorExtensions = originalObject.extensions ? originalObject.extensions : getVendorExtensions(originalObject);
2465
+ const vendorExtensionKeys = Object.keys(vendorExtensions);
2466
+ if (vendorExtensionKeys.length === 0) {
2467
+ return null;
2468
+ }
2469
+ return (React.createElement(React.Fragment, null, renderExtensionAddon({
2470
+ nestingLevel: -1,
2471
+ schemaNode: originalObject,
2472
+ vendorExtensions,
2473
+ })));
2474
+ });
2475
+ NodeVendorExtensions.displayName = 'NodeVendorExtensions';
2476
+
2346
2477
  const TwoColumnLayout = React__default.forwardRef(({ header, right, left, className }, ref) => (React__default.createElement(VStack, { ref: ref, w: "full", className: className, spacing: 8 },
2347
2478
  header,
2348
2479
  React__default.createElement(Flex, null,
@@ -2500,7 +2631,7 @@ const Body = ({ body, onChange }) => {
2500
2631
  var _a;
2501
2632
  const [refResolver, maxRefDepth] = useSchemaInlineRefResolver();
2502
2633
  const [chosenContent, setChosenContent] = React.useState(0);
2503
- const { nodeHasChanged } = useOptionsCtx();
2634
+ const { nodeHasChanged, renderExtensionAddon } = useOptionsCtx();
2504
2635
  React.useEffect(() => {
2505
2636
  onChange === null || onChange === void 0 ? void 0 : onChange(chosenContent);
2506
2637
  }, [chosenContent]);
@@ -2515,7 +2646,7 @@ const Body = ({ body, onChange }) => {
2515
2646
  description && (React.createElement(Box, { pos: "relative" },
2516
2647
  React.createElement(MarkdownViewer, { markdown: description }),
2517
2648
  React.createElement(NodeAnnotation, { change: descriptionChanged }))),
2518
- isJSONSchema(schema) && (React.createElement(JsonSchemaViewer, { resolveRef: refResolver, maxRefDepth: maxRefDepth, schema: getOriginalObject(schema), viewMode: "write", renderRootTreeLines: true, nodeHasChanged: nodeHasChanged }))));
2649
+ isJSONSchema(schema) && (React.createElement(JsonSchemaViewer, { resolveRef: refResolver, maxRefDepth: maxRefDepth, schema: getOriginalObject(schema), viewMode: "write", renderRootTreeLines: true, nodeHasChanged: nodeHasChanged, renderExtensionAddon: renderExtensionAddon }))));
2519
2650
  };
2520
2651
  Body.displayName = 'HttpOperation.Body';
2521
2652
 
@@ -2539,12 +2670,12 @@ const defaultStyle = {
2539
2670
  cookie: HttpParamStyles.Form,
2540
2671
  };
2541
2672
  const Parameters = ({ parameters, parameterType }) => {
2542
- const { nodeHasChanged } = useOptionsCtx();
2673
+ const { nodeHasChanged, renderExtensionAddon } = useOptionsCtx();
2543
2674
  const [refResolver, maxRefDepth] = useSchemaInlineRefResolver();
2544
2675
  const schema = React.useMemo(() => httpOperationParamsToSchema({ parameters, parameterType }), [parameters, parameterType]);
2545
2676
  if (!schema)
2546
2677
  return null;
2547
- return (React.createElement(JsonSchemaViewer, { resolveRef: refResolver, maxRefDepth: maxRefDepth, schema: schema, disableCrumbs: true, nodeHasChanged: nodeHasChanged }));
2678
+ return (React.createElement(JsonSchemaViewer, { resolveRef: refResolver, maxRefDepth: maxRefDepth, schema: schema, disableCrumbs: true, nodeHasChanged: nodeHasChanged, renderExtensionAddon: renderExtensionAddon }));
2548
2679
  };
2549
2680
  Parameters.displayName = 'HttpOperation.Parameters';
2550
2681
  const httpOperationParamsToSchema = ({ parameters, parameterType }) => {
@@ -2684,7 +2815,7 @@ const Response = ({ response, onMediaTypeChange }) => {
2684
2815
  const { contents = [], headers = [], description } = response;
2685
2816
  const [chosenContent, setChosenContent] = React.useState(0);
2686
2817
  const [refResolver, maxRefDepth] = useSchemaInlineRefResolver();
2687
- const { nodeHasChanged } = useOptionsCtx();
2818
+ const { nodeHasChanged, renderExtensionAddon } = useOptionsCtx();
2688
2819
  const responseContent = contents[chosenContent];
2689
2820
  const schema = responseContent === null || responseContent === void 0 ? void 0 : responseContent.schema;
2690
2821
  React.useEffect(() => {
@@ -2702,7 +2833,7 @@ const Response = ({ response, onMediaTypeChange }) => {
2702
2833
  React.createElement(SectionSubtitle, { title: "Body", id: "response-body" },
2703
2834
  React.createElement(Flex, { flex: 1, justify: "end" },
2704
2835
  React.createElement(Select, { "aria-label": "Response Body Content Type", value: String(chosenContent), onChange: value => setChosenContent(parseInt(String(value), 10)), options: contents.map((content, index) => ({ label: content.mediaType, value: index })), size: "sm" }))),
2705
- schema && (React.createElement(JsonSchemaViewer, { schema: getOriginalObject(schema), resolveRef: refResolver, maxRefDepth: maxRefDepth, viewMode: "read", parentCrumbs: ['responses', response.code], renderRootTreeLines: true, nodeHasChanged: nodeHasChanged }))))));
2836
+ schema && (React.createElement(JsonSchemaViewer, { schema: getOriginalObject(schema), resolveRef: refResolver, maxRefDepth: maxRefDepth, viewMode: "read", parentCrumbs: ['responses', response.code], renderRootTreeLines: true, nodeHasChanged: nodeHasChanged, renderExtensionAddon: renderExtensionAddon }))))));
2706
2837
  };
2707
2838
  Response.displayName = 'HttpOperation.Response';
2708
2839
  const codeToIntentVal = (code) => {
@@ -2778,6 +2909,7 @@ const HttpOperationComponent = React.memo(({ className, data: unresolvedData, la
2778
2909
  data.description && (React.createElement(Box, { pos: "relative" },
2779
2910
  React.createElement(MarkdownViewer, { className: "HttpOperation__Description", markdown: data.description }),
2780
2911
  React.createElement(NodeAnnotation, { change: descriptionChanged }))),
2912
+ React.createElement(NodeVendorExtensions, { data: data }),
2781
2913
  React.createElement(Request, { onChange: setTextRequestBodyIndex, operation: data }),
2782
2914
  data.responses && (React.createElement(Responses, { responses: data.responses, onMediaTypeChange: setResponseMediaType, onStatusCodeChange: setResponseStatusCode, isCompact: isCompact })),
2783
2915
  ((_a = data.callbacks) === null || _a === void 0 ? void 0 : _a.length) ? React.createElement(Callbacks, { callbacks: data.callbacks, isCompact: isCompact }) : null,
@@ -3029,7 +3161,7 @@ const ModelComponent = ({ data: unresolvedData, className, nodeTitle, layoutOpti
3029
3161
  var _a, _b;
3030
3162
  const [resolveRef, maxRefDepth] = useSchemaInlineRefResolver();
3031
3163
  const data = useResolvedObject(unresolvedData);
3032
- const { nodeHasChanged } = useOptionsCtx();
3164
+ const { nodeHasChanged, renderExtensionAddon } = useOptionsCtx();
3033
3165
  const { ref: layoutRef, isCompact } = useIsCompact(layoutOptions);
3034
3166
  const nodeId = (_a = data === null || data === void 0 ? void 0 : data['x-stoplight']) === null || _a === void 0 ? void 0 : _a.id;
3035
3167
  const title = (_b = data.title) !== null && _b !== void 0 ? _b : nodeTitle;
@@ -3052,8 +3184,9 @@ const ModelComponent = ({ data: unresolvedData, className, nodeTitle, layoutOpti
3052
3184
  data.description && data.type === 'object' && (React.createElement(Box, { pos: "relative" },
3053
3185
  React.createElement(MarkdownViewer, { role: "textbox", markdown: data.description }),
3054
3186
  React.createElement(NodeAnnotation, { change: descriptionChanged }))),
3187
+ React.createElement(NodeVendorExtensions, { data: data }),
3055
3188
  isCompact && modelExamples,
3056
- React.createElement(JsonSchemaViewer, { resolveRef: resolveRef, maxRefDepth: maxRefDepth, schema: getOriginalObject(data), nodeHasChanged: nodeHasChanged, skipTopLevelDescription: true })));
3189
+ React.createElement(JsonSchemaViewer, { resolveRef: resolveRef, maxRefDepth: maxRefDepth, schema: getOriginalObject(data), nodeHasChanged: nodeHasChanged, renderExtensionAddon: renderExtensionAddon, skipTopLevelDescription: true })));
3057
3190
  return (React.createElement(TwoColumnLayout, { ref: layoutRef, className: cn('Model', className), header: header, left: description, right: !isCompact && modelExamples }));
3058
3191
  };
3059
3192
  const ModelExamples = React.memo(({ data, isCollapsible = false }) => {
@@ -3076,7 +3209,7 @@ const Model = withErrorBoundary(ModelComponent, { recoverableProps: ['data'] });
3076
3209
 
3077
3210
  const Docs = React.memo((_a) => {
3078
3211
  var _b;
3079
- var { nodeType, nodeData, useNodeForRefResolving = false, refResolver, maxRefDepth, nodeHasChanged } = _a, commonProps = __rest(_a, ["nodeType", "nodeData", "useNodeForRefResolving", "refResolver", "maxRefDepth", "nodeHasChanged"]);
3212
+ var { nodeType, nodeData, useNodeForRefResolving = false, refResolver, maxRefDepth, nodeHasChanged, renderExtensionAddon } = _a, commonProps = __rest(_a, ["nodeType", "nodeData", "useNodeForRefResolving", "refResolver", "maxRefDepth", "nodeHasChanged", "renderExtensionAddon"]);
3080
3213
  const parsedNode = useParsedData(nodeType, nodeData);
3081
3214
  if (!parsedNode) {
3082
3215
  (_b = commonProps.nodeUnsupported) === null || _b === void 0 ? void 0 : _b.call(commonProps, 'dataEmpty');
@@ -3086,7 +3219,7 @@ const Docs = React.memo((_a) => {
3086
3219
  if (useNodeForRefResolving) {
3087
3220
  elem = (React.createElement(InlineRefResolverProvider, { document: parsedNode.data, resolver: refResolver, maxRefDepth: maxRefDepth }, elem));
3088
3221
  }
3089
- return React.createElement(ElementsOptionsProvider, { nodeHasChanged: nodeHasChanged }, elem);
3222
+ return (React.createElement(ElementsOptionsProvider, { nodeHasChanged: nodeHasChanged, renderExtensionAddon: renderExtensionAddon }, elem));
3090
3223
  });
3091
3224
  const ParsedDocs = (_a) => {
3092
3225
  var { node, nodeUnsupported } = _a, commonProps = __rest(_a, ["node", "nodeUnsupported"]);
@@ -3192,6 +3325,9 @@ const NODE_META_COLOR = {
3192
3325
  put: 'warning',
3193
3326
  patch: 'warning',
3194
3327
  delete: 'danger',
3328
+ head: '#9061F9',
3329
+ options: '#0D5AA7',
3330
+ trace: '#0D0B28',
3195
3331
  };
3196
3332
 
3197
3333
  function getHtmlIdFromItemId(id) {
@@ -3545,12 +3681,13 @@ function isPartialHttpRequest(maybeHttpRequest) {
3545
3681
  }
3546
3682
  const SchemaAndDescription = ({ title: titleProp, schema }) => {
3547
3683
  const [resolveRef, maxRefDepth] = useSchemaInlineRefResolver();
3684
+ const { renderExtensionAddon } = useOptionsCtx();
3548
3685
  const title = titleProp !== null && titleProp !== void 0 ? titleProp : schema.title;
3549
3686
  return (React__default.createElement(Box, { py: 2 },
3550
3687
  title && (React__default.createElement(Flex, { alignItems: "center", p: 2 },
3551
3688
  React__default.createElement(Icon, { icon: NodeTypeIconDefs[NodeType.Model], color: NodeTypeColors[NodeType.Model] }),
3552
3689
  React__default.createElement(Box, { color: "muted", px: 2 }, title))),
3553
- React__default.createElement(JsonSchemaViewer, { resolveRef: resolveRef, maxRefDepth: maxRefDepth, schema: getOriginalObject(schema) })));
3690
+ React__default.createElement(JsonSchemaViewer, { resolveRef: resolveRef, maxRefDepth: maxRefDepth, schema: getOriginalObject(schema), renderExtensionAddon: renderExtensionAddon })));
3554
3691
  };
3555
3692
  const CodeComponent = props => {
3556
3693
  const { title, jsonSchema, http, resolved, children } = props;
@@ -3895,4 +4032,4 @@ const createElementClass = (Component, propDescriptors) => {
3895
4032
  };
3896
4033
  };
3897
4034
 
3898
- export { DeprecatedBadge, Docs, ExportButton, HttpMethodColors, InlineRefResolverProvider, LinkHeading, Logo, MarkdownComponentsProvider, MockingProvider, NodeTypeColors, NodeTypeIconDefs, NodeTypePrettyName, NonIdealState, ParsedDocs, PersistenceContextProvider, PoweredByLink, ReactRouterMarkdownLink, ResponsiveSidebarLayout, RouterTypeContext, SidebarLayout, Styled, TableOfContents, TryIt, TryItWithRequestSamples, createElementClass, createResolvedObject, findFirstNode, isHttpOperation, isHttpService, isHttpWebhookOperation, slugify, useBundleRefsIntoDocument, useParsedData, useParsedValue, useResponsiveLayout, useRouter, withMosaicProvider, withPersistenceBoundary, withQueryClientProvider, withRouter, withStyles };
4035
+ export { DeprecatedBadge, Docs, ElementsOptionsProvider, ExportButton, HttpMethodColors, InlineRefResolverProvider, LinkHeading, Logo, MarkdownComponentsProvider, MockingProvider, NodeTypeColors, NodeTypeIconDefs, NodeTypePrettyName, NonIdealState, ParsedDocs, PersistenceContextProvider, PoweredByLink, ReactRouterMarkdownLink, ResponsiveSidebarLayout, RouterTypeContext, SidebarLayout, Styled, TableOfContents, TryIt, TryItWithRequestSamples, createElementClass, createResolvedObject, findFirstNode, isHttpOperation, isHttpService, isHttpWebhookOperation, slugify, useBundleRefsIntoDocument, useParsedData, useParsedValue, useResponsiveLayout, useRouter, withMosaicProvider, withPersistenceBoundary, withQueryClientProvider, withRouter, withStyles };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stoplight/elements-core",
3
- "version": "8.1.4",
3
+ "version": "8.3.1",
4
4
  "main": "./index.js",
5
5
  "sideEffects": [
6
6
  "web-components.min.js",
@@ -25,9 +25,9 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "@stoplight/http-spec": "^7.0.3",
28
- "@stoplight/json": "^3.18.1",
29
- "@stoplight/json-schema-ref-parser": "^9.0.5",
30
- "@stoplight/json-schema-sampler": "0.2.3",
28
+ "@stoplight/json": "^3.21.0",
29
+ "@stoplight/json-schema-ref-parser": "^9.2.7",
30
+ "@stoplight/json-schema-sampler": "0.3.0",
31
31
  "@stoplight/json-schema-tree": "^4.0.0",
32
32
  "@stoplight/json-schema-viewer": "4.16.1",
33
33
  "@stoplight/markdown-viewer": "^5.7.0",
@@ -37,7 +37,7 @@
37
37
  "@stoplight/path": "^1.3.2",
38
38
  "@stoplight/react-error-boundary": "^3.0.0",
39
39
  "@stoplight/types": "^14.1.1",
40
- "@stoplight/yaml": "^4.2.3",
40
+ "@stoplight/yaml": "^4.3.0",
41
41
  "classnames": "^2.2.6",
42
42
  "httpsnippet-lite": "^3.0.5",
43
43
  "jotai": "1.3.9",