docusaurus-theme-openapi-docs 2.0.2 → 2.0.4

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.
Files changed (31) hide show
  1. package/lib/theme/ApiExplorer/Body/index.js +8 -1
  2. package/lib/theme/ApiExplorer/CodeSnippets/code-snippets-types.d.ts +21 -0
  3. package/lib/theme/ApiExplorer/CodeSnippets/code-snippets-types.js +8 -0
  4. package/lib/theme/ApiExplorer/CodeSnippets/index.d.ts +2 -12
  5. package/lib/theme/ApiExplorer/CodeSnippets/index.js +87 -8
  6. package/lib/theme/ApiExplorer/CodeSnippets/languages.d.ts +2 -0
  7. package/lib/theme/ApiExplorer/CodeSnippets/languages.js +32 -0
  8. package/lib/theme/ApiExplorer/CodeTabs/_CodeTabs.scss +14 -0
  9. package/lib/theme/ApiExplorer/CodeTabs/index.js +7 -0
  10. package/lib/theme/ApiExplorer/index.js +1 -1
  11. package/lib/theme/ApiTabs/index.js +11 -3
  12. package/lib/theme/Markdown/index.js +37 -0
  13. package/lib/theme/OperationTabs/_OperationTabs.scss +68 -0
  14. package/lib/theme/OperationTabs/index.js +187 -0
  15. package/lib/theme/styles.scss +1 -0
  16. package/package.json +3 -3
  17. package/src/theme/ApiExplorer/Body/index.tsx +3 -1
  18. package/src/theme/ApiExplorer/CodeSnippets/code-snippets-types.ts +55 -0
  19. package/src/theme/ApiExplorer/CodeSnippets/index.tsx +94 -21
  20. package/src/theme/ApiExplorer/CodeSnippets/languages.ts +37 -0
  21. package/src/theme/ApiExplorer/CodeTabs/_CodeTabs.scss +14 -0
  22. package/src/theme/ApiExplorer/CodeTabs/index.js +7 -0
  23. package/src/theme/ApiExplorer/index.tsx +1 -1
  24. package/src/theme/ApiTabs/index.js +11 -3
  25. package/src/theme/Markdown/index.js +37 -0
  26. package/src/theme/OperationTabs/_OperationTabs.scss +68 -0
  27. package/src/theme/OperationTabs/index.js +187 -0
  28. package/src/theme/styles.scss +1 -0
  29. package/src/theme-openapi.d.ts +4 -0
  30. package/lib/theme/ApiExplorer/CodeSnippets/languages.json +0 -1386
  31. package/src/theme/ApiExplorer/CodeSnippets/languages.json +0 -1386
@@ -0,0 +1,187 @@
1
+ /* ============================================================================
2
+ * Copyright (c) Palo Alto Networks
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ * ========================================================================== */
7
+
8
+ import React, { cloneElement, useEffect, useState, useRef } from "react";
9
+
10
+ import {
11
+ useScrollPositionBlocker,
12
+ useTabs,
13
+ } from "@docusaurus/theme-common/internal";
14
+ import useIsBrowser from "@docusaurus/useIsBrowser";
15
+ import clsx from "clsx";
16
+
17
+ function TabList({ className, block, selectedValue, selectValue, tabValues }) {
18
+ const tabRefs = [];
19
+ const { blockElementScrollPositionUntilNextRender } =
20
+ useScrollPositionBlocker();
21
+
22
+ const handleTabChange = (event) => {
23
+ event.preventDefault();
24
+ const newTab = event.currentTarget;
25
+ const newTabIndex = tabRefs.indexOf(newTab);
26
+ const newTabValue = tabValues[newTabIndex].value;
27
+ // custom
28
+ if (newTabValue !== selectedValue) {
29
+ blockElementScrollPositionUntilNextRender(newTab);
30
+ selectValue(newTabValue);
31
+ }
32
+ };
33
+
34
+ const handleKeydown = (event) => {
35
+ let focusElement = null;
36
+ switch (event.key) {
37
+ case "Enter": {
38
+ handleTabChange(event);
39
+ break;
40
+ }
41
+ case "ArrowRight": {
42
+ const nextTab = tabRefs.indexOf(event.currentTarget) + 1;
43
+ focusElement = tabRefs[nextTab] ?? tabRefs[0];
44
+ break;
45
+ }
46
+ case "ArrowLeft": {
47
+ const prevTab = tabRefs.indexOf(event.currentTarget) - 1;
48
+ focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1];
49
+ break;
50
+ }
51
+ default:
52
+ break;
53
+ }
54
+ focusElement?.focus();
55
+ };
56
+
57
+ const tabItemListContainerRef = useRef(null);
58
+ const [showTabArrows, setShowTabArrows] = useState(false);
59
+
60
+ useEffect(() => {
61
+ const resizeObserver = new ResizeObserver((entries) => {
62
+ for (let entry of entries) {
63
+ if (entry.target.offsetWidth < entry.target.scrollWidth) {
64
+ setShowTabArrows(true);
65
+ } else {
66
+ setShowTabArrows(false);
67
+ }
68
+ }
69
+ });
70
+
71
+ resizeObserver.observe(tabItemListContainerRef.current);
72
+
73
+ return () => {
74
+ resizeObserver.disconnect();
75
+ };
76
+ }, []);
77
+
78
+ const handleRightClick = () => {
79
+ tabItemListContainerRef.current.scrollLeft += 90;
80
+ };
81
+
82
+ const handleLeftClick = () => {
83
+ tabItemListContainerRef.current.scrollLeft -= 90;
84
+ };
85
+
86
+ return (
87
+ <div className="tabs__container">
88
+ <div className="openapi-tabs__operation-container">
89
+ {showTabArrows && (
90
+ <button
91
+ className={clsx("openapi-tabs__arrow", "left")}
92
+ onClick={handleLeftClick}
93
+ />
94
+ )}
95
+ <ul
96
+ ref={tabItemListContainerRef}
97
+ role="tablist"
98
+ aria-orientation="horizontal"
99
+ className={clsx(
100
+ "openapi-tabs__operation-list-container",
101
+ "tabs",
102
+ {
103
+ "tabs--block": block,
104
+ },
105
+ className
106
+ )}
107
+ >
108
+ {tabValues.map(({ value, label, attributes }) => {
109
+ return (
110
+ <li
111
+ role="tab"
112
+ tabIndex={selectedValue === value ? 0 : -1}
113
+ aria-selected={selectedValue === value}
114
+ key={value}
115
+ ref={(tabControl) => tabRefs.push(tabControl)}
116
+ onKeyDown={handleKeydown}
117
+ onFocus={handleTabChange}
118
+ onClick={(e) => handleTabChange(e)}
119
+ {...attributes}
120
+ className={clsx(
121
+ "tabs__item",
122
+ "openapi-tabs__operation-item",
123
+ attributes?.className,
124
+ {
125
+ active: selectedValue === value,
126
+ }
127
+ )}
128
+ >
129
+ {label ?? value}
130
+ </li>
131
+ );
132
+ })}
133
+ </ul>
134
+ {showTabArrows && (
135
+ <button
136
+ className={clsx("openapi-tabs__arrow", "right")}
137
+ onClick={handleRightClick}
138
+ />
139
+ )}
140
+ </div>
141
+ </div>
142
+ );
143
+ }
144
+ function TabContent({ lazy, children, selectedValue }) {
145
+ // eslint-disable-next-line no-param-reassign
146
+ children = Array.isArray(children) ? children : [children];
147
+ if (lazy) {
148
+ const selectedTabItem = children.find(
149
+ (tabItem) => tabItem.props.value === selectedValue
150
+ );
151
+ if (!selectedTabItem) {
152
+ // fail-safe or fail-fast? not sure what's best here
153
+ return null;
154
+ }
155
+ return cloneElement(selectedTabItem, { className: "margin-top--md" });
156
+ }
157
+ return (
158
+ <div className="margin-top--md">
159
+ {children.map((tabItem, i) =>
160
+ cloneElement(tabItem, {
161
+ key: i,
162
+ hidden: tabItem.props.value !== selectedValue,
163
+ })
164
+ )}
165
+ </div>
166
+ );
167
+ }
168
+ function TabsComponent(props) {
169
+ const tabs = useTabs(props);
170
+ return (
171
+ <div className="tabs-container">
172
+ <TabList {...props} {...tabs} />
173
+ <TabContent {...props} {...tabs} />
174
+ </div>
175
+ );
176
+ }
177
+ export default function OperationTabs(props) {
178
+ const isBrowser = useIsBrowser();
179
+ return (
180
+ <TabsComponent
181
+ // Remount tabs after hydration
182
+ // Temporary fix for https://github.com/facebook/docusaurus/issues/5653
183
+ key={String(isBrowser)}
184
+ {...props}
185
+ />
186
+ );
187
+ }
@@ -36,6 +36,7 @@
36
36
  @use "./DiscriminatorTabs/DiscriminatorTabs";
37
37
  @use "./MimeTabs/MimeTabs";
38
38
  @use "./SchemaTabs/SchemaTabs";
39
+ @use "./OperationTabs/OperationTabs";
39
40
  /* Code Samples */
40
41
  @use "./ResponseSamples/ResponseSamples";
41
42
  /* Markdown Styling */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "docusaurus-theme-openapi-docs",
3
3
  "description": "OpenAPI theme for Docusaurus.",
4
- "version": "2.0.2",
4
+ "version": "2.0.4",
5
5
  "license": "MIT",
6
6
  "keywords": [
7
7
  "openapi",
@@ -43,7 +43,7 @@
43
43
  "clsx": "^1.1.1",
44
44
  "copy-text-to-clipboard": "^3.1.0",
45
45
  "crypto-js": "^4.1.1",
46
- "docusaurus-plugin-openapi-docs": "^2.0.2",
46
+ "docusaurus-plugin-openapi-docs": "^2.0.4",
47
47
  "docusaurus-plugin-sass": "^0.2.3",
48
48
  "file-saver": "^2.0.5",
49
49
  "lodash": "^4.17.20",
@@ -68,5 +68,5 @@
68
68
  "engines": {
69
69
  "node": ">=14"
70
70
  },
71
- "gitHead": "7f9528595b373f7691fd63845d84870549e6895c"
71
+ "gitHead": "71012fa9a8e21d7d83beaf6368b93381298a3e2e"
72
72
  }
@@ -14,6 +14,7 @@ import FormSelect from "@theme/ApiExplorer/FormSelect";
14
14
  import FormTextInput from "@theme/ApiExplorer/FormTextInput";
15
15
  import LiveApp from "@theme/ApiExplorer/LiveEditor";
16
16
  import { useTypedDispatch, useTypedSelector } from "@theme/ApiItem/hooks";
17
+ import Markdown from "@theme/Markdown";
17
18
  import SchemaTabs from "@theme/SchemaTabs";
18
19
  import TabItem from "@theme/TabItem";
19
20
  import { RequestBodyObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
@@ -303,6 +304,7 @@ function Body({
303
304
  </TabItem>
304
305
  {/* @ts-ignore */}
305
306
  <TabItem label="Example" value="example">
307
+ {example.summary && <Markdown children={example.summary} />}
306
308
  {exampleBody && (
307
309
  <LiveApp
308
310
  action={dispatch}
@@ -340,7 +342,7 @@ function Body({
340
342
  value={example.label}
341
343
  key={example.label}
342
344
  >
343
- {example.summary && <p>{example.summary}</p>}
345
+ {example.summary && <Markdown children={example.summary} />}
344
346
  {example.body && (
345
347
  <LiveApp action={dispatch} language={language}>
346
348
  {example.body}
@@ -0,0 +1,55 @@
1
+ /* ============================================================================
2
+ * Copyright (c) Palo Alto Networks
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ * ========================================================================== */
7
+
8
+ // https://github.com/github-linguist/linguist/blob/master/lib/linguist/popular.yml
9
+ export type CodeSampleLanguage =
10
+ | "C"
11
+ | "C#"
12
+ | "C++"
13
+ | "CoffeeScript"
14
+ | "CSS"
15
+ | "Dart"
16
+ | "DM"
17
+ | "Elixir"
18
+ | "Go"
19
+ | "Groovy"
20
+ | "HTML"
21
+ | "Java"
22
+ | "JavaScript"
23
+ | "Kotlin"
24
+ | "Objective-C"
25
+ | "Perl"
26
+ | "PHP"
27
+ | "PowerShell"
28
+ | "Python"
29
+ | "Ruby"
30
+ | "Rust"
31
+ | "Scala"
32
+ | "Shell"
33
+ | "Swift"
34
+ | "TypeScript";
35
+
36
+ export interface Language {
37
+ highlight: string;
38
+ language: string;
39
+ codeSampleLanguage: CodeSampleLanguage;
40
+ logoClass: string;
41
+ variant: string;
42
+ variants: string[];
43
+ options?: { [key: string]: boolean };
44
+ sample?: string;
45
+ samples?: string[];
46
+ samplesSources?: string[];
47
+ samplesLabels?: string[];
48
+ }
49
+
50
+ // https://redocly.com/docs/api-reference-docs/specification-extensions/x-code-samples
51
+ export interface CodeSample {
52
+ source: string;
53
+ lang: CodeSampleLanguage;
54
+ label?: string;
55
+ }
@@ -16,20 +16,14 @@ import CodeTabs from "@theme/ApiExplorer/CodeTabs";
16
16
  import { useTypedSelector } from "@theme/ApiItem/hooks";
17
17
  import merge from "lodash/merge";
18
18
 
19
- export interface Language {
20
- highlight: string;
21
- language: string;
22
- logoClass: string;
23
- variant: string;
24
- variants: string[];
25
- options: { [key: string]: boolean };
26
- source?: string;
27
- }
19
+ import { CodeSample, Language } from "./code-snippets-types";
20
+ import { mergeCodeSampleLanguage } from "./languages";
28
21
 
29
22
  export const languageSet: Language[] = [
30
23
  {
31
24
  highlight: "bash",
32
25
  language: "curl",
26
+ codeSampleLanguage: "Shell",
33
27
  logoClass: "bash",
34
28
  options: {
35
29
  longFormat: false,
@@ -42,6 +36,7 @@ export const languageSet: Language[] = [
42
36
  {
43
37
  highlight: "python",
44
38
  language: "python",
39
+ codeSampleLanguage: "Python",
45
40
  logoClass: "python",
46
41
  options: {
47
42
  followRedirect: true,
@@ -53,6 +48,7 @@ export const languageSet: Language[] = [
53
48
  {
54
49
  highlight: "go",
55
50
  language: "go",
51
+ codeSampleLanguage: "Go",
56
52
  logoClass: "go",
57
53
  options: {
58
54
  followRedirect: true,
@@ -64,6 +60,7 @@ export const languageSet: Language[] = [
64
60
  {
65
61
  highlight: "javascript",
66
62
  language: "nodejs",
63
+ codeSampleLanguage: "JavaScript",
67
64
  logoClass: "nodejs",
68
65
  options: {
69
66
  ES6_enabled: true,
@@ -71,11 +68,12 @@ export const languageSet: Language[] = [
71
68
  trimRequestBody: true,
72
69
  },
73
70
  variant: "axios",
74
- variants: ["axios", "native", "request", "unirest"],
71
+ variants: ["axios", "native"],
75
72
  },
76
73
  {
77
74
  highlight: "ruby",
78
75
  language: "ruby",
76
+ codeSampleLanguage: "Ruby",
79
77
  logoClass: "ruby",
80
78
  options: {
81
79
  followRedirect: true,
@@ -87,6 +85,7 @@ export const languageSet: Language[] = [
87
85
  {
88
86
  highlight: "csharp",
89
87
  language: "csharp",
88
+ codeSampleLanguage: "C#",
90
89
  logoClass: "csharp",
91
90
  options: {
92
91
  followRedirect: true,
@@ -98,6 +97,7 @@ export const languageSet: Language[] = [
98
97
  {
99
98
  highlight: "php",
100
99
  language: "php",
100
+ codeSampleLanguage: "PHP",
101
101
  logoClass: "php",
102
102
  options: {
103
103
  followRedirect: true,
@@ -109,6 +109,7 @@ export const languageSet: Language[] = [
109
109
  {
110
110
  highlight: "java",
111
111
  language: "java",
112
+ codeSampleLanguage: "Java",
112
113
  logoClass: "java",
113
114
  options: {
114
115
  followRedirect: true,
@@ -120,6 +121,7 @@ export const languageSet: Language[] = [
120
121
  {
121
122
  highlight: "powershell",
122
123
  language: "powershell",
124
+ codeSampleLanguage: "PowerShell",
123
125
  logoClass: "powershell",
124
126
  options: {
125
127
  followRedirect: true,
@@ -132,10 +134,10 @@ export const languageSet: Language[] = [
132
134
 
133
135
  export interface Props {
134
136
  postman: sdk.Request;
135
- codeSamples: any; // TODO: Type this...
137
+ codeSamples: CodeSample[];
136
138
  }
137
139
 
138
- function CodeTab({ children, hidden, className, onClick }: any): JSX.Element {
140
+ function CodeTab({ children, hidden, className }: any): JSX.Element {
139
141
  return (
140
142
  <div role="tabpanel" className={className} {...{ hidden }}>
141
143
  {children}
@@ -165,7 +167,6 @@ function CodeSnippets({ postman, codeSamples }: Props) {
165
167
  const langs = [
166
168
  ...((siteConfig?.themeConfig?.languageTabs as Language[] | undefined) ??
167
169
  languageSet),
168
- ...codeSamples,
169
170
  ];
170
171
 
171
172
  // Filter languageSet by user-defined langs
@@ -176,14 +177,18 @@ function CodeSnippets({ postman, codeSamples }: Props) {
176
177
  });
177
178
 
178
179
  // Merge user-defined langs into languageSet
179
- const mergedLangs = merge(filteredLanguageSet, langs);
180
+ const mergedLangs = mergeCodeSampleLanguage(
181
+ merge(filteredLanguageSet, langs),
182
+ codeSamples
183
+ );
180
184
 
181
185
  // Read defaultLang from localStorage
182
186
  const defaultLang: Language[] = mergedLangs.filter(
183
187
  (lang) =>
184
188
  lang.language === localStorage.getItem("docusaurus.tab.code-samples")
185
189
  );
186
- const [selectedVariant, setSelectedVariant] = useState();
190
+ const [selectedVariant, setSelectedVariant] = useState<string | undefined>();
191
+ const [selectedSample, setSelectedSample] = useState<string | undefined>();
187
192
  const [language, setLanguage] = useState(() => {
188
193
  // Return first index if only 1 user-defined language exists
189
194
  if (mergedLangs.length === 1) {
@@ -192,9 +197,23 @@ function CodeSnippets({ postman, codeSamples }: Props) {
192
197
  // Fall back to language in localStorage or first user-defined language
193
198
  return defaultLang[0] ?? mergedLangs[0];
194
199
  });
195
- const [codeText, setCodeText] = useState("");
200
+ const [codeText, setCodeText] = useState<string>("");
201
+ const [codeSampleCodeText, setCodeSampleCodeText] = useState<string>("");
196
202
 
197
203
  useEffect(() => {
204
+ // initial active language is custom code sample
205
+ if (
206
+ language &&
207
+ language.sample &&
208
+ language.samples &&
209
+ language.samplesSources
210
+ ) {
211
+ const sampleIndex = language.samples.findIndex(
212
+ (smp) => smp === language.sample
213
+ );
214
+ setCodeSampleCodeText(language.samplesSources[sampleIndex]);
215
+ }
216
+
198
217
  if (language && !!language.options) {
199
218
  const postmanRequest = buildPostmanRequest(postman, {
200
219
  queryParams,
@@ -219,8 +238,6 @@ function CodeSnippets({ postman, codeSamples }: Props) {
219
238
  setCodeText(snippet);
220
239
  }
221
240
  );
222
- } else if (language && !!language.source) {
223
- setCodeText(language.source);
224
241
  } else if (language && !language.options) {
225
242
  const langSource = mergedLangs.filter(
226
243
  (lang) => lang.language === language.language
@@ -271,8 +288,8 @@ function CodeSnippets({ postman, codeSamples }: Props) {
271
288
  auth,
272
289
  mergedLangs,
273
290
  ]);
274
-
275
- useEffect(() => {
291
+ // no dependencies was intentionlly set for this particular hook. it's safe as long as if conditions are set
292
+ useEffect(function onSelectedVariantUpdate() {
276
293
  if (selectedVariant && selectedVariant !== language.variant) {
277
294
  const postmanRequest = buildPostmanRequest(postman, {
278
295
  queryParams,
@@ -300,6 +317,22 @@ function CodeSnippets({ postman, codeSamples }: Props) {
300
317
  }
301
318
  });
302
319
 
320
+ // no dependencies was intentionlly set for this particular hook. it's safe as long as if conditions are set
321
+ // eslint-disable-next-line react-hooks/exhaustive-deps
322
+ useEffect(function onSelectedSampleUpdate() {
323
+ if (
324
+ language.samples &&
325
+ language.samplesSources &&
326
+ selectedSample &&
327
+ selectedSample !== language.sample
328
+ ) {
329
+ const sampleIndex = language.samples.findIndex(
330
+ (smp) => smp === selectedSample
331
+ );
332
+ setCodeSampleCodeText(language.samplesSources[sampleIndex]);
333
+ }
334
+ });
335
+
303
336
  if (language === undefined) {
304
337
  return null;
305
338
  }
@@ -324,6 +357,46 @@ function CodeSnippets({ postman, codeSamples }: Props) {
324
357
  className: `openapi-tabs__code-item--${lang.logoClass}`,
325
358
  }}
326
359
  >
360
+ {lang.samples && (
361
+ <CodeTabs
362
+ className="openapi-tabs__code-container-inner"
363
+ action={{
364
+ setLanguage: setLanguage,
365
+ setSelectedSample: setSelectedSample,
366
+ }}
367
+ includeSample={true}
368
+ currentLanguage={lang.language}
369
+ defaultValue={selectedSample}
370
+ lazy
371
+ >
372
+ {lang.samples.map((sample, index) => {
373
+ return (
374
+ <CodeTab
375
+ value={sample}
376
+ label={
377
+ lang.samplesLabels
378
+ ? lang.samplesLabels[index]
379
+ : sample
380
+ }
381
+ key={`${lang.language}-${lang.sample}`}
382
+ attributes={{
383
+ className: `openapi-tabs__code-item--sample`,
384
+ }}
385
+ >
386
+ {/* @ts-ignore */}
387
+ <ApiCodeBlock
388
+ language={lang.highlight}
389
+ className="openapi-explorer__code-block"
390
+ showLineNumbers={true}
391
+ >
392
+ {codeSampleCodeText}
393
+ </ApiCodeBlock>
394
+ </CodeTab>
395
+ );
396
+ })}
397
+ </CodeTabs>
398
+ )}
399
+
327
400
  <CodeTabs
328
401
  className="openapi-tabs__code-container-inner"
329
402
  action={{
@@ -335,7 +408,7 @@ function CodeSnippets({ postman, codeSamples }: Props) {
335
408
  defaultValue={selectedVariant}
336
409
  lazy
337
410
  >
338
- {lang.variants.map((variant) => {
411
+ {lang.variants.map((variant, index) => {
339
412
  return (
340
413
  <CodeTab
341
414
  value={variant.toLowerCase()}
@@ -0,0 +1,37 @@
1
+ /* ============================================================================
2
+ * Copyright (c) Palo Alto Networks
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ * ========================================================================== */
7
+
8
+ import { CodeSample, Language } from "./code-snippets-types";
9
+
10
+ export function mergeCodeSampleLanguage(
11
+ languages: Language[],
12
+ codeSamples: CodeSample[]
13
+ ): Language[] {
14
+ return languages.map((language) => {
15
+ const languageCodeSamples = codeSamples.filter(
16
+ ({ lang }) => lang === language.codeSampleLanguage
17
+ );
18
+
19
+ if (languageCodeSamples.length) {
20
+ const samples = languageCodeSamples.map(({ lang }) => lang);
21
+ const samplesLabels = languageCodeSamples.map(
22
+ ({ label, lang }) => label || lang
23
+ );
24
+ const samplesSources = languageCodeSamples.map(({ source }) => source);
25
+
26
+ return {
27
+ ...language,
28
+ sample: samples[0],
29
+ samples,
30
+ samplesSources,
31
+ samplesLabels,
32
+ };
33
+ }
34
+
35
+ return language;
36
+ });
37
+ }
@@ -94,6 +94,20 @@ body[class="ReactModal__Body--open"] {
94
94
  padding-right: 0.5rem !important;
95
95
  }
96
96
 
97
+ .openapi-tabs__code-item--sample {
98
+ color: var(--ifm-color-secondary);
99
+
100
+ &.active {
101
+ border-color: var(--ifm-toc-border-color);
102
+ }
103
+ }
104
+
105
+ .openapi-tabs__code-item--sample > span {
106
+ padding-top: unset !important;
107
+ padding-left: 0.5rem !important;
108
+ padding-right: 0.5rem !important;
109
+ }
110
+
97
111
  .openapi-tabs__code-item--python {
98
112
  color: var(--ifm-color-success);
99
113
 
@@ -19,6 +19,7 @@ function TabList({
19
19
  action,
20
20
  currentLanguage,
21
21
  includeVariant,
22
+ includeSample,
22
23
  className,
23
24
  block,
24
25
  selectedValue,
@@ -53,6 +54,12 @@ function TabList({
53
54
  )[0];
54
55
  action.setSelectedVariant(newLanguage.variant.toLowerCase());
55
56
  }
57
+
58
+ if (currentLanguage && includeSample) {
59
+ newLanguage.sample = newTabValue;
60
+ action.setSelectedSample(newTabValue.toLowerCase());
61
+ }
62
+
56
63
  action.setLanguage(newLanguage);
57
64
  }
58
65
  };
@@ -30,7 +30,7 @@ function ApiExplorer({
30
30
  {item.method !== "event" && (
31
31
  <CodeSnippets
32
32
  postman={postman}
33
- codeSamples={(item as any)["x-code-samples"] ?? []}
33
+ codeSamples={(item as any)["x-codeSamples"] ?? []}
34
34
  />
35
35
  )}
36
36
  <Request item={item} />
@@ -15,7 +15,15 @@ import useIsBrowser from "@docusaurus/useIsBrowser";
15
15
  import Heading from "@theme/Heading";
16
16
  import clsx from "clsx";
17
17
 
18
- function TabList({ className, block, selectedValue, selectValue, tabValues }) {
18
+ function TabList({
19
+ className,
20
+ block,
21
+ selectedValue,
22
+ selectValue,
23
+ tabValues,
24
+ label = "Responses",
25
+ id = "responses",
26
+ }) {
19
27
  const tabRefs = [];
20
28
  const { blockElementScrollPositionUntilNextRender } =
21
29
  useScrollPositionBlocker();
@@ -84,8 +92,8 @@ function TabList({ className, block, selectedValue, selectValue, tabValues }) {
84
92
 
85
93
  return (
86
94
  <div className="openapi-tabs__response-header-section">
87
- <Heading as="h2" id="responses" className="openapi-tabs__response-header">
88
- Responses
95
+ <Heading as="h2" id={id} className="openapi-tabs__response-header">
96
+ {label}
89
97
  </Heading>
90
98
  <div className="openapi-tabs__response-container">
91
99
  {showTabArrows && (