docusaurus-theme-openapi-docs 1.0.4 → 1.1.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.
Files changed (103) hide show
  1. package/lib/theme/ApiDemoPanel/Body/index.js +11 -9
  2. package/lib/theme/ApiDemoPanel/Body/json2xml.js +43 -0
  3. package/lib/theme/ApiDemoPanel/CodeTabs/index.js +193 -0
  4. package/lib/theme/ApiDemoPanel/CodeTabs/styles.module.css +11 -0
  5. package/lib/theme/ApiDemoPanel/Curl/index.js +41 -110
  6. package/lib/theme/ApiDemoPanel/FloatingButton/index.js +4 -2
  7. package/lib/theme/ApiDemoPanel/FloatingButton/styles.module.css +3 -2
  8. package/lib/theme/ApiDemoPanel/LiveEditor/index.js +74 -0
  9. package/lib/theme/ApiDemoPanel/LiveEditor/styles.module.css +35 -0
  10. package/lib/theme/ApiDemoPanel/ParamOptions/styles.module.css +0 -4
  11. package/lib/theme/ApiDemoPanel/Server/index.js +1 -1
  12. package/lib/theme/ApiDemoPanel/Server/styles.module.css +0 -4
  13. package/lib/theme/ApiItem/Content/index.js +65 -0
  14. package/lib/theme/ApiItem/Footer/index.js +78 -0
  15. package/lib/theme/ApiItem/Footer/styles.module.css +18 -0
  16. package/lib/theme/ApiItem/Layout/icons/bash-original.svg +1 -0
  17. package/lib/theme/ApiItem/Layout/icons/go-original-wordmark.svg +1 -0
  18. package/lib/theme/ApiItem/Layout/icons/javascript-original.svg +1 -0
  19. package/lib/theme/ApiItem/Layout/icons/linux-original.svg +1 -0
  20. package/lib/theme/ApiItem/Layout/icons/python-original.svg +1 -0
  21. package/lib/theme/ApiItem/Layout/index.js +93 -0
  22. package/lib/theme/ApiItem/{styles.module.css → Layout/styles.module.css} +114 -4
  23. package/lib/theme/ApiItem/Metadata/index.js +32 -0
  24. package/lib/theme/ApiItem/Paginator/index.js +33 -0
  25. package/lib/theme/ApiItem/TOC/Desktop/index.js +31 -0
  26. package/lib/theme/ApiItem/TOC/Mobile/index.js +35 -0
  27. package/lib/theme/ApiItem/TOC/Mobile/styles.module.css +19 -0
  28. package/lib/theme/ApiItem/index.js +37 -126
  29. package/lib/theme/ApiTabs/index.js +17 -6
  30. package/lib/theme/ApiTabs/styles.module.css +0 -1
  31. package/lib/theme/SchemaTabs/index.js +258 -0
  32. package/lib/theme/SchemaTabs/styles.module.css +110 -0
  33. package/lib-next/theme/ApiDemoPanel/Body/index.js +11 -15
  34. package/lib-next/theme/ApiDemoPanel/Body/json2xml.js +43 -0
  35. package/lib-next/theme/ApiDemoPanel/CodeTabs/index.js +215 -0
  36. package/lib-next/theme/ApiDemoPanel/CodeTabs/styles.module.css +11 -0
  37. package/lib-next/theme/ApiDemoPanel/Curl/index.js +46 -135
  38. package/lib-next/theme/ApiDemoPanel/FloatingButton/index.js +6 -2
  39. package/lib-next/theme/ApiDemoPanel/FloatingButton/styles.module.css +3 -2
  40. package/lib-next/theme/ApiDemoPanel/LiveEditor/index.js +60 -0
  41. package/lib-next/theme/ApiDemoPanel/LiveEditor/styles.module.css +35 -0
  42. package/lib-next/theme/ApiDemoPanel/ParamOptions/styles.module.css +0 -4
  43. package/lib-next/theme/ApiDemoPanel/Server/index.js +1 -0
  44. package/lib-next/theme/ApiDemoPanel/Server/styles.module.css +0 -4
  45. package/lib-next/theme/ApiItem/Content/index.js +55 -0
  46. package/lib-next/theme/ApiItem/Footer/index.js +88 -0
  47. package/lib-next/theme/ApiItem/Footer/styles.module.css +18 -0
  48. package/lib-next/theme/ApiItem/Layout/icons/bash-original.svg +1 -0
  49. package/lib-next/theme/ApiItem/Layout/icons/go-original-wordmark.svg +1 -0
  50. package/lib-next/theme/ApiItem/Layout/icons/javascript-original.svg +1 -0
  51. package/lib-next/theme/ApiItem/Layout/icons/linux-original.svg +1 -0
  52. package/lib-next/theme/ApiItem/Layout/icons/python-original.svg +1 -0
  53. package/lib-next/theme/ApiItem/Layout/index.js +69 -0
  54. package/{src/theme/ApiItem → lib-next/theme/ApiItem/Layout}/styles.module.css +114 -4
  55. package/lib-next/theme/ApiItem/Metadata/index.js +21 -0
  56. package/lib-next/theme/ApiItem/Paginator/index.js +19 -0
  57. package/lib-next/theme/ApiItem/TOC/Desktop/index.js +22 -0
  58. package/lib-next/theme/ApiItem/TOC/Mobile/index.js +24 -0
  59. package/lib-next/theme/ApiItem/TOC/Mobile/styles.module.css +19 -0
  60. package/lib-next/theme/ApiItem/index.js +31 -133
  61. package/lib-next/theme/ApiTabs/index.js +17 -6
  62. package/lib-next/theme/ApiTabs/styles.module.css +0 -1
  63. package/lib-next/theme/SchemaTabs/index.js +258 -0
  64. package/lib-next/theme/SchemaTabs/styles.module.css +110 -0
  65. package/package.json +7 -9
  66. package/src/theme/ApiDemoPanel/Body/index.tsx +9 -13
  67. package/src/theme/ApiDemoPanel/Body/json2xml.js +43 -0
  68. package/src/theme/ApiDemoPanel/CodeTabs/index.tsx +238 -0
  69. package/src/theme/ApiDemoPanel/CodeTabs/styles.module.css +11 -0
  70. package/src/theme/ApiDemoPanel/Curl/index.tsx +45 -124
  71. package/src/theme/ApiDemoPanel/FloatingButton/index.tsx +6 -2
  72. package/src/theme/ApiDemoPanel/FloatingButton/styles.module.css +3 -2
  73. package/src/theme/ApiDemoPanel/LiveEditor/index.tsx +71 -0
  74. package/src/theme/ApiDemoPanel/LiveEditor/styles.module.css +35 -0
  75. package/src/theme/ApiDemoPanel/ParamOptions/styles.module.css +0 -4
  76. package/src/theme/ApiDemoPanel/Server/index.tsx +1 -0
  77. package/src/theme/ApiDemoPanel/Server/styles.module.css +0 -4
  78. package/src/theme/ApiItem/Content/index.tsx +57 -0
  79. package/src/theme/ApiItem/Footer/index.tsx +101 -0
  80. package/src/theme/ApiItem/Footer/styles.module.css +18 -0
  81. package/src/theme/ApiItem/Layout/icons/bash-original.svg +1 -0
  82. package/src/theme/ApiItem/Layout/icons/go-original-wordmark.svg +1 -0
  83. package/src/theme/ApiItem/Layout/icons/javascript-original.svg +1 -0
  84. package/src/theme/ApiItem/Layout/icons/linux-original.svg +1 -0
  85. package/src/theme/ApiItem/Layout/icons/python-original.svg +1 -0
  86. package/src/theme/ApiItem/Layout/index.tsx +78 -0
  87. package/{lib-next/theme/ApiItem → src/theme/ApiItem/Layout}/styles.module.css +114 -4
  88. package/src/theme/ApiItem/Metadata/index.tsx +24 -0
  89. package/src/theme/ApiItem/Paginator/index.tsx +21 -0
  90. package/src/theme/ApiItem/TOC/Desktop/index.tsx +25 -0
  91. package/src/theme/ApiItem/TOC/Mobile/index.tsx +28 -0
  92. package/src/theme/ApiItem/TOC/Mobile/styles.module.css +19 -0
  93. package/src/theme/ApiItem/index.tsx +31 -130
  94. package/src/theme/ApiTabs/index.js +17 -6
  95. package/src/theme/ApiTabs/styles.module.css +0 -1
  96. package/src/theme/SchemaTabs/index.js +258 -0
  97. package/src/theme/SchemaTabs/styles.module.css +110 -0
  98. package/lib/theme/ApiDemoPanel/VSCode/index.js +0 -252
  99. package/lib/theme/ApiDemoPanel/VSCode/styles.module.css +0 -19
  100. package/lib-next/theme/ApiDemoPanel/VSCode/index.js +0 -265
  101. package/lib-next/theme/ApiDemoPanel/VSCode/styles.module.css +0 -19
  102. package/src/theme/ApiDemoPanel/VSCode/index.tsx +0 -205
  103. package/src/theme/ApiDemoPanel/VSCode/styles.module.css +0 -19
@@ -0,0 +1,258 @@
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, {
9
+ Children,
10
+ cloneElement,
11
+ isValidElement,
12
+ useEffect,
13
+ useRef,
14
+ useState,
15
+ } from "react";
16
+
17
+ import { duplicates } from "@docusaurus/theme-common";
18
+ import useIsBrowser from "@docusaurus/useIsBrowser";
19
+ import clsx from "clsx";
20
+
21
+ import styles from "./styles.module.css"; // A very rough duck type, but good enough to guard against mistakes while
22
+
23
+ const {
24
+ useScrollPositionBlocker,
25
+ useTabGroupChoice,
26
+ } = require("@docusaurus/theme-common/internal");
27
+
28
+ // allowing customization
29
+
30
+ function isTabItem(comp) {
31
+ return typeof comp.props.value !== "undefined";
32
+ }
33
+
34
+ function SchemaTabsComponent(props) {
35
+ const {
36
+ lazy,
37
+ block,
38
+ defaultValue: defaultValueProp,
39
+ values: valuesProp,
40
+ groupId,
41
+ className,
42
+ } = props;
43
+ const children = Children.map(props.children, (child) => {
44
+ if (isValidElement(child) && isTabItem(child)) {
45
+ return child;
46
+ } // child.type.name will give non-sensical values in prod because of
47
+ // minification, but we assume it won't throw in prod.
48
+
49
+ throw new Error(
50
+ `Docusaurus error: Bad <Tabs> child <${
51
+ // @ts-expect-error: guarding against unexpected cases
52
+ typeof child.type === "string" ? child.type : child.type.name
53
+ }>: all children of the <Tabs> component should be <TabItem>, and every <TabItem> should have a unique "value" prop.`
54
+ );
55
+ });
56
+ const values =
57
+ valuesProp ?? // We only pick keys that we recognize. MDX would inject some keys by default
58
+ children.map(({ props: { value, label, attributes } }) => ({
59
+ value,
60
+ label,
61
+ attributes,
62
+ }));
63
+ const dup = duplicates(values, (a, b) => a.value === b.value);
64
+
65
+ if (dup.length > 0) {
66
+ throw new Error(
67
+ `Docusaurus error: Duplicate values "${dup
68
+ .map((a) => a.value)
69
+ .join(", ")}" found in <Tabs>. Every value needs to be unique.`
70
+ );
71
+ } // When defaultValueProp is null, don't show a default tab
72
+
73
+ const defaultValue =
74
+ defaultValueProp === null
75
+ ? defaultValueProp
76
+ : defaultValueProp ??
77
+ children.find((child) => child.props.default)?.props.value ??
78
+ children[0]?.props.value;
79
+
80
+ if (defaultValue !== null && !values.some((a) => a.value === defaultValue)) {
81
+ throw new Error(
82
+ `Docusaurus error: The <Tabs> has a defaultValue "${defaultValue}" but none of its children has the corresponding value. Available values are: ${values
83
+ .map((a) => a.value)
84
+ .join(
85
+ ", "
86
+ )}. If you intend to show no default tab, use defaultValue={null} instead.`
87
+ );
88
+ }
89
+
90
+ const { tabGroupChoices, setTabGroupChoices } = useTabGroupChoice();
91
+ const [selectedValue, setSelectedValue] = useState(defaultValue);
92
+ const tabRefs = [];
93
+ const { blockElementScrollPositionUntilNextRender } =
94
+ useScrollPositionBlocker();
95
+
96
+ if (groupId != null) {
97
+ const relevantTabGroupChoice = tabGroupChoices[groupId];
98
+
99
+ if (
100
+ relevantTabGroupChoice != null &&
101
+ relevantTabGroupChoice !== selectedValue &&
102
+ values.some((value) => value.value === relevantTabGroupChoice)
103
+ ) {
104
+ setSelectedValue(relevantTabGroupChoice);
105
+ }
106
+ }
107
+
108
+ const handleTabChange = (event) => {
109
+ const newTab = event.currentTarget;
110
+ const newTabIndex = tabRefs.indexOf(newTab);
111
+ const newTabValue = values[newTabIndex].value;
112
+
113
+ if (newTabValue !== selectedValue) {
114
+ blockElementScrollPositionUntilNextRender(newTab);
115
+ setSelectedValue(newTabValue);
116
+
117
+ if (groupId != null) {
118
+ setTabGroupChoices(groupId, newTabValue);
119
+ }
120
+ }
121
+ };
122
+
123
+ const handleKeydown = (event) => {
124
+ let focusElement = null;
125
+
126
+ switch (event.key) {
127
+ case "ArrowRight": {
128
+ const nextTab = tabRefs.indexOf(event.currentTarget) + 1;
129
+ focusElement = tabRefs[nextTab] || tabRefs[0];
130
+ break;
131
+ }
132
+
133
+ case "ArrowLeft": {
134
+ const prevTab = tabRefs.indexOf(event.currentTarget) - 1;
135
+ focusElement = tabRefs[prevTab] || tabRefs[tabRefs.length - 1];
136
+ break;
137
+ }
138
+
139
+ default:
140
+ break;
141
+ }
142
+
143
+ focusElement?.focus();
144
+ };
145
+
146
+ const tabItemListContainerRef = useRef(null);
147
+ const [showTabArrows, setShowTabArrows] = useState(false);
148
+
149
+ useEffect(() => {
150
+ const tabOffsetWidth = tabItemListContainerRef.current.offsetWidth;
151
+ const tabScrollWidth = tabItemListContainerRef.current.scrollWidth;
152
+
153
+ if (tabOffsetWidth < tabScrollWidth) {
154
+ setShowTabArrows(true);
155
+ }
156
+ }, []);
157
+
158
+ const handleRightClick = () => {
159
+ tabItemListContainerRef.current.scrollLeft += 90;
160
+ };
161
+
162
+ const handleLeftClick = () => {
163
+ tabItemListContainerRef.current.scrollLeft -= 90;
164
+ };
165
+
166
+ return (
167
+ <div className="tabs__container">
168
+ <div className={styles.schemaTabsTopSection}>
169
+ <div className={styles.schemaTabsContainer}>
170
+ {showTabArrows && (
171
+ <button
172
+ className={clsx(styles.tabArrow, styles.tabArrowLeft)}
173
+ onClick={handleLeftClick}
174
+ />
175
+ )}
176
+ <ul
177
+ ref={tabItemListContainerRef}
178
+ role="tablist"
179
+ aria-orientation="horizontal"
180
+ className={clsx(
181
+ styles.schemaTabsListContainer,
182
+ "tabs",
183
+ {
184
+ "tabs--block": block,
185
+ },
186
+ className
187
+ )}
188
+ >
189
+ {values.map(({ value, label, attributes }) => {
190
+ return (
191
+ <li
192
+ role="tab"
193
+ tabIndex={selectedValue === value ? 0 : -1}
194
+ aria-selected={selectedValue === value}
195
+ key={value}
196
+ ref={(tabControl) => tabRefs.push(tabControl)}
197
+ onKeyDown={handleKeydown}
198
+ onFocus={handleTabChange}
199
+ onClick={handleTabChange}
200
+ {...attributes}
201
+ className={clsx(
202
+ "tabs__item",
203
+ styles.tabItem,
204
+ attributes?.className,
205
+ {
206
+ [styles.schemaTabActive]: selectedValue === value,
207
+ }
208
+ )}
209
+ >
210
+ <span className={styles.schemaTabLabel}>
211
+ {label ?? value}
212
+ </span>
213
+ </li>
214
+ );
215
+ })}
216
+ </ul>
217
+ {showTabArrows && (
218
+ <button
219
+ className={clsx(styles.tabArrow, styles.tabArrowRight)}
220
+ onClick={handleRightClick}
221
+ />
222
+ )}
223
+ </div>
224
+ </div>
225
+ <hr />
226
+ {lazy ? (
227
+ cloneElement(
228
+ children.filter(
229
+ (tabItem) => tabItem.props.value === selectedValue
230
+ )[0],
231
+ {
232
+ className: clsx("margin-vert--md", styles.schemaTabsContainer),
233
+ }
234
+ )
235
+ ) : (
236
+ <div className={clsx("margin-vert--md", styles.schemaTabsContainer)}>
237
+ {children.map((tabItem, i) =>
238
+ cloneElement(tabItem, {
239
+ key: i,
240
+ hidden: tabItem.props.value !== selectedValue,
241
+ })
242
+ )}
243
+ </div>
244
+ )}
245
+ </div>
246
+ );
247
+ }
248
+
249
+ export default function SchemaTabs(props) {
250
+ const isBrowser = useIsBrowser();
251
+ return (
252
+ <SchemaTabsComponent // Remount tabs after hydration
253
+ // Temporary fix for https://github.com/facebook/docusaurus/issues/5653
254
+ key={String(isBrowser)}
255
+ {...props}
256
+ />
257
+ );
258
+ }
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
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
+ .tabItem {
9
+ display: flex;
10
+ align-items: center;
11
+ justify-content: center;
12
+ height: 1.8rem;
13
+ margin-top: 0 !important;
14
+ margin-right: 0.5rem;
15
+ border: 1px solid var(--openapi-code-dim-dark);
16
+ border-radius: var(--ifm-global-radius);
17
+ color: var(--openapi-code-dim-dark);
18
+ font-size: 12px;
19
+ }
20
+
21
+ .tabItem:hover {
22
+ color: var(--ifm-color-emphasis-500) !important;
23
+ }
24
+
25
+ .tabItem:last-child {
26
+ margin-right: 0 !important;
27
+ }
28
+
29
+ /* Open API Schema Tabs */
30
+ .schemaTabsTopSection {
31
+ margin-top: 1rem;
32
+ display: flex;
33
+ justify-content: space-between;
34
+ align-items: center;
35
+ }
36
+
37
+ .schemaTabsTopSection + hr {
38
+ display: none;
39
+ }
40
+
41
+ .schemaTabsContainer {
42
+ display: flex;
43
+ align-items: center;
44
+ max-width: 390px;
45
+ padding-left: 3px;
46
+ overflow: hidden;
47
+ }
48
+
49
+ .schemaTabsListContainer {
50
+ padding: 0 0.25rem;
51
+ overflow-y: hidden;
52
+ overflow-x: scroll;
53
+ scroll-behavior: smooth;
54
+ }
55
+
56
+ .schemaTabsListContainer::-webkit-scrollbar {
57
+ display: none;
58
+ }
59
+
60
+ .tabItem.schemaTabActive {
61
+ border: 1px solid var(--ifm-color-primary);
62
+ color: var(--ifm-color-primary);
63
+ }
64
+
65
+ .schemaTabLabel {
66
+ white-space: nowrap;
67
+ }
68
+
69
+ .schemaTabsContainer {
70
+ max-width: 600px;
71
+ }
72
+
73
+ /* Tab Arrows */
74
+ .tabArrow {
75
+ content: "";
76
+ height: 1.25rem;
77
+ width: 1.25rem;
78
+ padding: 0 0.75rem;
79
+ border: none;
80
+ min-width: 1.25rem;
81
+ background: var(--ifm-menu-link-sublist-icon) 50% / 2rem 2rem;
82
+ filter: var(--ifm-menu-link-sublist-icon-filter);
83
+ }
84
+
85
+ .tabArrow:hover {
86
+ cursor: pointer;
87
+ }
88
+
89
+ .tabArrowLeft {
90
+ transform: rotate(270deg);
91
+ }
92
+
93
+ .tabArrowRight {
94
+ transform: rotate(90deg);
95
+ }
96
+
97
+ @media screen and (max-width: 500px) {
98
+ .schemaTabsTopSection {
99
+ flex-direction: column;
100
+ align-items: flex-start;
101
+ }
102
+
103
+ .schemaTabsContainer {
104
+ width: 100%;
105
+ }
106
+
107
+ .tabItem {
108
+ height: 100%;
109
+ }
110
+ }
@@ -8,17 +8,18 @@ import React from "react";
8
8
  import ContentType from "../ContentType";
9
9
  import FormSelect from "../FormSelect";
10
10
  import { useTypedDispatch, useTypedSelector } from "../hooks";
11
+ import LiveApp from "../LiveEditor";
11
12
  import FormFileUpload from "./../FormFileUpload";
12
13
  import FormItem from "./../FormItem";
13
- import FormTextInput from "./../FormTextInput";
14
- import VSCode from "./../VSCode";
14
+ import FormTextInput from "./../FormTextInput"; // @ts-ignore
15
+
16
+ import json2xml from "./json2xml";
15
17
  import {
16
18
  clearFormBodyKey,
17
19
  clearRawBody,
18
20
  setFileFormBody,
19
21
  setFileRawBody,
20
22
  setStringFormBody,
21
- setStringRawBody,
22
23
  } from "./slice";
23
24
 
24
25
  function BodyWrap({ requestBodyMetadata, jsonRequestBodyExample }) {
@@ -186,23 +187,18 @@ function Body({ requestBodyMetadata, jsonRequestBodyExample }) {
186
187
  }
187
188
 
188
189
  if (contentType === "application/xml") {
190
+ if (jsonRequestBodyExample) {
191
+ exampleBodyString = json2xml(jsonRequestBodyExample);
192
+ }
193
+
189
194
  language = "xml";
190
195
  }
191
196
 
192
197
  return (
193
198
  <FormItem label="Body">
194
- <VSCode
195
- value={exampleBodyString}
196
- language={language}
197
- onChange={(value) => {
198
- if (value.trim() === "") {
199
- dispatch(clearRawBody());
200
- return;
201
- }
202
-
203
- dispatch(setStringRawBody(value));
204
- }}
205
- />
199
+ <LiveApp action={dispatch} language={language}>
200
+ {exampleBodyString}
201
+ </LiveApp>
206
202
  </FormItem>
207
203
  );
208
204
  }
@@ -0,0 +1,43 @@
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
+ export default function json2xml(o, tab) {
9
+ var toXml = function (v, name, ind) {
10
+ var xml = "";
11
+ if (v instanceof Array) {
12
+ for (var i = 0, n = v.length; i < n; i++)
13
+ xml += ind + toXml(v[i], name, ind + "\t") + "\n";
14
+ } else if (typeof v == "object") {
15
+ var hasChild = false;
16
+ xml += ind + "<" + name;
17
+ for (var m in v) {
18
+ if (m.charAt(0) === "@")
19
+ xml += " " + m.substr(1) + '="' + v[m].toString() + '"';
20
+ else hasChild = true;
21
+ }
22
+ xml += hasChild ? ">" : "/>";
23
+ if (hasChild) {
24
+ for (var m2 in v) {
25
+ if (m2 === "#text") xml += v[m2];
26
+ else if (m2 === "#cdata") xml += "<![CDATA[" + v[m2] + "]]>";
27
+ else if (m2.charAt(0) !== "@") xml += toXml(v[m2], m2, ind + "\t");
28
+ }
29
+ xml +=
30
+ (xml.charAt(xml.length - 1) === "\n" ? ind : "") +
31
+ "</" +
32
+ name +
33
+ ">";
34
+ }
35
+ } else {
36
+ xml += ind + "<" + name + ">" + v.toString() + "</" + name + ">";
37
+ }
38
+ return xml;
39
+ },
40
+ xml = "";
41
+ for (var m3 in o) xml += toXml(o[m3], m3, "");
42
+ return tab ? xml.replace(/\t/g, tab) : xml.replace(/\t|\n/g, "");
43
+ }
@@ -0,0 +1,215 @@
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
+ import React, { useState, cloneElement, isValidElement } from "react";
8
+ import { duplicates } from "@docusaurus/theme-common";
9
+ import useIsBrowser from "@docusaurus/useIsBrowser";
10
+ import clsx from "clsx";
11
+ import { languageSet } from "../Curl";
12
+ import styles from "./styles.module.css";
13
+
14
+ const {
15
+ useScrollPositionBlocker,
16
+ useTabGroupChoice,
17
+ } = require("@docusaurus/theme-common/internal"); // A very rough duck type, but good enough to guard against mistakes while
18
+ // allowing customization
19
+
20
+ function isTabItem(comp) {
21
+ return "value" in comp.props;
22
+ }
23
+
24
+ function TabsComponent(props) {
25
+ const {
26
+ lazy,
27
+ block,
28
+ defaultValue: defaultValueProp,
29
+ values: valuesProp,
30
+ groupId,
31
+ className,
32
+ action,
33
+ } = props;
34
+ const children = React.Children.map(props.children, (child) => {
35
+ if (isValidElement(child) && isTabItem(child)) {
36
+ return child;
37
+ } // child.type.name will give non-sensical values in prod because of
38
+ // minification, but we assume it won't throw in prod.
39
+
40
+ throw new Error(
41
+ `Docusaurus error: Bad <Tabs> child <${
42
+ // @ts-expect-error: guarding against unexpected cases
43
+ typeof child.type === "string" ? child.type : child.type.name
44
+ }>: all children of the <Tabs> component should be <TabItem>, and every <TabItem> should have a unique "value" prop.`
45
+ );
46
+ });
47
+ const values =
48
+ valuesProp ?? // Only pick keys that we recognize. MDX would inject some keys by default
49
+ children.map(({ props: { value, label, attributes } }) => ({
50
+ value,
51
+ label,
52
+ attributes,
53
+ }));
54
+ const dup = duplicates(values, (a, b) => a.value === b.value);
55
+
56
+ if (dup.length > 0) {
57
+ throw new Error(
58
+ `Docusaurus error: Duplicate values "${dup
59
+ .map((a) => a.value)
60
+ .join(", ")}" found in <Tabs>. Every value needs to be unique.`
61
+ );
62
+ } // When defaultValueProp is null, don't show a default tab
63
+
64
+ const defaultValue =
65
+ defaultValueProp === null
66
+ ? defaultValueProp
67
+ : defaultValueProp ??
68
+ children.find((child) => child.props.default)?.props.value ??
69
+ children[0].props.value;
70
+
71
+ if (defaultValue !== null && !values.some((a) => a.value === defaultValue)) {
72
+ throw new Error(
73
+ `Docusaurus error: The <Tabs> has a defaultValue "${defaultValue}" but none of its children has the corresponding value. Available values are: ${values
74
+ .map((a) => a.value)
75
+ .join(
76
+ ", "
77
+ )}. If you intend to show no default tab, use defaultValue={null} instead.`
78
+ );
79
+ }
80
+
81
+ const { tabGroupChoices, setTabGroupChoices } = useTabGroupChoice();
82
+ const [selectedValue, setSelectedValue] = useState(defaultValue);
83
+ const tabRefs = [];
84
+ const { blockElementScrollPositionUntilNextRender } =
85
+ useScrollPositionBlocker();
86
+
87
+ if (groupId != null) {
88
+ const relevantTabGroupChoice = tabGroupChoices[groupId];
89
+
90
+ if (
91
+ relevantTabGroupChoice != null &&
92
+ relevantTabGroupChoice !== selectedValue &&
93
+ values.some((value) => value.value === relevantTabGroupChoice)
94
+ ) {
95
+ setSelectedValue(relevantTabGroupChoice);
96
+ }
97
+ }
98
+
99
+ const handleTabChange = (event) => {
100
+ const newTab = event.currentTarget;
101
+ const newTabIndex = tabRefs.indexOf(newTab);
102
+ const newTabValue = values[newTabIndex].value;
103
+
104
+ if (newTabValue !== selectedValue) {
105
+ blockElementScrollPositionUntilNextRender(newTab);
106
+ setSelectedValue(newTabValue);
107
+
108
+ if (action) {
109
+ const newLanguage = languageSet.filter(
110
+ (lang) => lang.language === newTabValue
111
+ );
112
+ action(newLanguage[0]);
113
+ }
114
+
115
+ if (groupId != null) {
116
+ setTabGroupChoices(groupId, String(newTabValue));
117
+ }
118
+ }
119
+ };
120
+
121
+ const handleKeydown = (event) => {
122
+ let focusElement = null;
123
+
124
+ switch (event.key) {
125
+ case "ArrowRight": {
126
+ const nextTab = tabRefs.indexOf(event.currentTarget) + 1;
127
+ focusElement = tabRefs[nextTab] ?? tabRefs[0];
128
+ break;
129
+ }
130
+
131
+ case "ArrowLeft": {
132
+ const prevTab = tabRefs.indexOf(event.currentTarget) - 1;
133
+ focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1];
134
+ break;
135
+ }
136
+
137
+ default:
138
+ break;
139
+ }
140
+
141
+ focusElement?.focus();
142
+ };
143
+
144
+ return (
145
+ <div className={clsx("tabs-container", styles.tabList)}>
146
+ <ul
147
+ role="tablist"
148
+ aria-orientation="horizontal"
149
+ className={clsx(
150
+ "tabs",
151
+ {
152
+ "tabs--block": block,
153
+ },
154
+ styles.code__tabs,
155
+ className
156
+ )}
157
+ >
158
+ {values.map(({ value, label, attributes }) => (
159
+ <li
160
+ role="tab"
161
+ tabIndex={selectedValue === value ? 0 : -1}
162
+ aria-selected={selectedValue === value}
163
+ key={value}
164
+ ref={(tabControl) => tabRefs.push(tabControl)}
165
+ onKeyDown={handleKeydown}
166
+ onFocus={handleTabChange}
167
+ onClick={handleTabChange}
168
+ {...attributes}
169
+ className={clsx(
170
+ "tabs__item",
171
+ styles.tabItem,
172
+ attributes?.className,
173
+ {
174
+ "tabs__item--active": selectedValue === value,
175
+ }
176
+ )}
177
+ >
178
+ {label ?? value}
179
+ </li>
180
+ ))}
181
+ </ul>
182
+
183
+ {lazy ? (
184
+ cloneElement(
185
+ children.filter(
186
+ (tabItem) => tabItem.props.value === selectedValue
187
+ )[0],
188
+ {
189
+ className: "margin-top--md",
190
+ }
191
+ )
192
+ ) : (
193
+ <div className="margin-top--md">
194
+ {children.map((tabItem, i) =>
195
+ cloneElement(tabItem, {
196
+ key: i,
197
+ hidden: tabItem.props.value !== selectedValue,
198
+ })
199
+ )}
200
+ </div>
201
+ )}
202
+ </div>
203
+ );
204
+ }
205
+
206
+ export default function CodeTabs(props) {
207
+ const isBrowser = useIsBrowser();
208
+ return (
209
+ <TabsComponent // Remount tabs after hydration
210
+ // Temporary fix for https://github.com/facebook/docusaurus/issues/5653
211
+ key={String(isBrowser)}
212
+ {...props}
213
+ />
214
+ );
215
+ }
@@ -0,0 +1,11 @@
1
+ .tabList {
2
+ margin-bottom: var(--ifm-leading);
3
+ }
4
+
5
+ .tabItem {
6
+ margin-top: 0 !important;
7
+ }
8
+
9
+ .code__tabs {
10
+ justify-content: space-around;
11
+ }