@digi-frontend/dgate-api-documentation 1.0.47 → 1.0.52

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 (158) hide show
  1. package/dist/_virtual/core.js +2 -0
  2. package/dist/_virtual/core.js.map +1 -0
  3. package/dist/_virtual/core2.js +2 -0
  4. package/dist/_virtual/core2.js.map +1 -0
  5. package/dist/_virtual/format.js +2 -0
  6. package/dist/_virtual/format.js.map +1 -0
  7. package/dist/_virtual/index3.js +1 -1
  8. package/dist/_virtual/index4.js +1 -1
  9. package/dist/_virtual/index5.js +1 -1
  10. package/dist/_virtual/index6.js +1 -1
  11. package/dist/f4452c3ebcf0d5da.svg +4 -0
  12. package/dist/node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js +2 -0
  13. package/dist/node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js.map +1 -0
  14. package/dist/node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js +2 -0
  15. package/dist/node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js.map +1 -0
  16. package/dist/node_modules/@babel/runtime/helpers/esm/defineProperty.js +2 -0
  17. package/dist/node_modules/@babel/runtime/helpers/esm/defineProperty.js.map +1 -0
  18. package/dist/node_modules/@babel/runtime/helpers/esm/extends.js +2 -0
  19. package/dist/node_modules/@babel/runtime/helpers/esm/extends.js.map +1 -0
  20. package/dist/node_modules/@babel/runtime/helpers/esm/iterableToArray.js +2 -0
  21. package/dist/node_modules/@babel/runtime/helpers/esm/iterableToArray.js.map +1 -0
  22. package/dist/node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js +2 -0
  23. package/dist/node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js.map +1 -0
  24. package/dist/node_modules/@babel/runtime/helpers/esm/objectWithoutProperties.js +2 -0
  25. package/dist/node_modules/@babel/runtime/helpers/esm/objectWithoutProperties.js.map +1 -0
  26. package/dist/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js +2 -0
  27. package/dist/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js.map +1 -0
  28. package/dist/node_modules/@babel/runtime/helpers/esm/toConsumableArray.js +2 -0
  29. package/dist/node_modules/@babel/runtime/helpers/esm/toConsumableArray.js.map +1 -0
  30. package/dist/node_modules/@babel/runtime/helpers/esm/toPrimitive.js +2 -0
  31. package/dist/node_modules/@babel/runtime/helpers/esm/toPrimitive.js.map +1 -0
  32. package/dist/node_modules/@babel/runtime/helpers/esm/toPropertyKey.js +2 -0
  33. package/dist/node_modules/@babel/runtime/helpers/esm/toPropertyKey.js.map +1 -0
  34. package/dist/node_modules/@babel/runtime/helpers/esm/typeof.js +2 -0
  35. package/dist/node_modules/@babel/runtime/helpers/esm/typeof.js.map +1 -0
  36. package/dist/node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js +2 -0
  37. package/dist/node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js.map +1 -0
  38. package/dist/node_modules/fault/index.js +2 -0
  39. package/dist/node_modules/fault/index.js.map +1 -0
  40. package/dist/node_modules/format/format.js +2 -0
  41. package/dist/node_modules/format/format.js.map +1 -0
  42. package/dist/node_modules/highlight.js/lib/core.js +2 -0
  43. package/dist/node_modules/highlight.js/lib/core.js.map +1 -0
  44. package/dist/node_modules/lowlight/lib/core.js +2 -0
  45. package/dist/node_modules/lowlight/lib/core.js.map +1 -0
  46. package/dist/node_modules/nanoid/index.js +2 -0
  47. package/dist/node_modules/nanoid/index.js.map +1 -0
  48. package/dist/node_modules/nanoid/url-alphabet/index.js +2 -0
  49. package/dist/node_modules/nanoid/url-alphabet/index.js.map +1 -0
  50. package/dist/node_modules/react-syntax-highlighter/dist/esm/checkForListedLanguage.js +2 -0
  51. package/dist/node_modules/react-syntax-highlighter/dist/esm/checkForListedLanguage.js.map +1 -0
  52. package/dist/node_modules/react-syntax-highlighter/dist/esm/create-element.js +2 -0
  53. package/dist/node_modules/react-syntax-highlighter/dist/esm/create-element.js.map +1 -0
  54. package/dist/node_modules/react-syntax-highlighter/dist/esm/highlight.js +2 -0
  55. package/dist/node_modules/react-syntax-highlighter/dist/esm/highlight.js.map +1 -0
  56. package/dist/node_modules/react-syntax-highlighter/dist/esm/light.js +2 -0
  57. package/dist/node_modules/react-syntax-highlighter/dist/esm/light.js.map +1 -0
  58. package/dist/node_modules/react-syntax-highlighter/dist/esm/styles/hljs/stackoverflow-dark.js +2 -0
  59. package/dist/node_modules/react-syntax-highlighter/dist/esm/styles/hljs/stackoverflow-dark.js.map +1 -0
  60. package/dist/node_modules/react-syntax-highlighter/dist/esm/styles/hljs/stackoverflow-light.js +2 -0
  61. package/dist/node_modules/react-syntax-highlighter/dist/esm/styles/hljs/stackoverflow-light.js.map +1 -0
  62. package/dist/node_modules/toposort/index.js +1 -1
  63. package/dist/node_modules/yup/index.esm.js +1 -1
  64. package/dist/src/assets/icons/UpArrow.svg.js +2 -0
  65. package/dist/src/assets/icons/UpArrow.svg.js.map +1 -0
  66. package/dist/src/assets/icons/copy.svg.js +2 -0
  67. package/dist/src/assets/icons/copy.svg.js.map +1 -0
  68. package/dist/src/components/MethodAccordion/MethodAccordion.js +1 -1
  69. package/dist/src/components/MethodAccordion/MethodAccordion.js.map +1 -1
  70. package/dist/src/components/dialog/index.js +1 -1
  71. package/dist/src/components/dialog/index.js.map +1 -1
  72. package/dist/src/components/table/table.js +1 -1
  73. package/dist/src/components/table/table.js.map +1 -1
  74. package/dist/src/constants/methods.constant.js +1 -1
  75. package/dist/src/constants/methods.constant.js.map +1 -1
  76. package/dist/src/helpers/docs.helper.js +2 -0
  77. package/dist/src/helpers/docs.helper.js.map +1 -0
  78. package/dist/src/helpers/layout.helper.js +1 -1
  79. package/dist/src/helpers/layout.helper.js.map +1 -1
  80. package/dist/src/layout/docsComponents/Codebox/Codebox.js +2 -0
  81. package/dist/src/layout/docsComponents/Codebox/Codebox.js.map +1 -0
  82. package/dist/src/layout/docsComponents/Codebox/style.module.scss.js +2 -0
  83. package/dist/src/layout/docsComponents/Codebox/style.module.scss.js.map +1 -0
  84. package/dist/src/layout/docsComponents/DocsAside/DocsAside.js +1 -1
  85. package/dist/src/layout/docsComponents/DocsAside/DocsAside.js.map +1 -1
  86. package/dist/src/layout/docsComponents/DocsAside/style.module.scss.js +2 -0
  87. package/dist/src/layout/docsComponents/DocsAside/style.module.scss.js.map +1 -0
  88. package/dist/src/layout/docsComponents/DocsContent/DocsContent.js +1 -1
  89. package/dist/src/layout/docsComponents/DocsContent/DocsContent.js.map +1 -1
  90. package/dist/src/layout/docsComponents/DocsContent/EndpointPage/index.js +1 -1
  91. package/dist/src/layout/docsComponents/DocsContent/EndpointPage/index.js.map +1 -1
  92. package/dist/src/layout/docsComponents/DocsContent/TagPage/index.js +2 -0
  93. package/dist/src/layout/docsComponents/DocsContent/TagPage/index.js.map +1 -0
  94. package/dist/src/layout/docsComponents/DocsHeader/DocsHeader.js +1 -1
  95. package/dist/src/layout/docsComponents/DocsHeader/DocsHeader.js.map +1 -1
  96. package/dist/src/layout/docsComponents/DocsSideMenuTree/DocsSideMenuTree.js +1 -1
  97. package/dist/src/layout/docsComponents/DocsSideMenuTree/DocsSideMenuTree.js.map +1 -1
  98. package/dist/src/layout/docsLayout.js +1 -1
  99. package/dist/src/layout/docsLayout.js.map +1 -1
  100. package/dist/src/layout/layout.js +1 -1
  101. package/dist/src/layout/layout.js.map +1 -1
  102. package/dist/src/layout/layout.module.css.js +1 -1
  103. package/dist/src/utils/index.js +2 -0
  104. package/dist/src/utils/index.js.map +1 -0
  105. package/dist/src/validator/form.scheme.js +1 -1
  106. package/dist/src/validator/form.scheme.js.map +1 -1
  107. package/dist/styles.css +1164 -892
  108. package/dist/types/assets/icons/index.d.ts +1 -0
  109. package/dist/types/components/dialog/dialog.d.ts +1 -0
  110. package/dist/types/components/dialog/index.d.ts +1 -1
  111. package/dist/types/helpers/docs.helper.d.ts +2 -2
  112. package/dist/types/layout/docsComponents/Codebox/Codebox.d.ts +4 -0
  113. package/dist/types/layout/docsComponents/DocsAside/DocsAside.d.ts +4 -2
  114. package/dist/types/layout/docsComponents/DocsContent/DocsContent.d.ts +5 -1
  115. package/dist/types/layout/docsComponents/DocsContent/EndpointPage/index.d.ts +3 -1
  116. package/dist/types/layout/docsComponents/DocsContent/TagPage/index.d.ts +6 -1
  117. package/dist/types/layout/docsComponents/DocsSideMenuTree/DocsSideMenuTree.d.ts +12 -5
  118. package/dist/types/layout/docsLayout.d.ts +5 -4
  119. package/dist/types/layout/layout.d.ts +1 -1
  120. package/dist/types/types/index.d.ts +27 -0
  121. package/dist/types/types/layout.type.d.ts +1 -0
  122. package/dist/types/types/openApi.d.ts +1 -0
  123. package/dist/types/utils/index.d.ts +1 -0
  124. package/dist/types/validator/form.scheme.d.ts +1 -0
  125. package/package.json +3 -3
  126. package/rollup.config.js +2 -0
  127. package/src/assets/icons/copy.svg +4 -0
  128. package/src/assets/icons/index.ts +1 -0
  129. package/src/components/MethodAccordion/MethodAccordion.module.scss +20 -11
  130. package/src/components/MethodAccordion/MethodAccordion.tsx +393 -17
  131. package/src/components/dialog/dialog.ts +1 -0
  132. package/src/components/dialog/index.tsx +27 -24
  133. package/src/components/table/table.tsx +5 -1
  134. package/src/constants/methods.constant.ts +1 -1
  135. package/src/helpers/docs.helper.ts +17 -4
  136. package/src/helpers/layout.helper.ts +19 -2
  137. package/src/layout/docsComponents/Codebox/Codebox.tsx +61 -0
  138. package/src/layout/docsComponents/Codebox/style.module.scss +43 -0
  139. package/src/layout/docsComponents/DocsAside/DocsAside.tsx +89 -4
  140. package/src/layout/docsComponents/DocsAside/style.module.scss +113 -0
  141. package/src/layout/docsComponents/DocsContent/DocsContent.tsx +25 -3
  142. package/src/layout/docsComponents/DocsContent/EndpointPage/index.tsx +134 -122
  143. package/src/layout/docsComponents/DocsContent/EndpointPage/style.scss +45 -0
  144. package/src/layout/docsComponents/DocsContent/TagPage/index.tsx +77 -74
  145. package/src/layout/docsComponents/DocsContent/TagPage/style.scss +42 -5
  146. package/src/layout/docsComponents/DocsHeader/DocsHeader.module.scss +78 -5
  147. package/src/layout/docsComponents/DocsHeader/DocsHeader.tsx +85 -15
  148. package/src/layout/docsComponents/DocsSideMenuTree/DocsSideMenuTree.tsx +119 -87
  149. package/src/layout/docsComponents/index.scss +3 -1
  150. package/src/layout/docsLayout.tsx +47 -18
  151. package/src/layout/layout.module.css +8 -5
  152. package/src/layout/layout.tsx +39 -21
  153. package/src/types/index.ts +28 -0
  154. package/src/types/layout.type.ts +1 -0
  155. package/src/types/openApi.ts +1 -0
  156. package/src/utils/index.ts +7 -0
  157. package/src/validator/form.scheme.ts +9 -1
  158. package/src/layout/docsComponents/DocsAside/style.scss +0 -3
@@ -17,7 +17,7 @@
17
17
  margin-left: 2.9375rem;
18
18
  }
19
19
 
20
- :global(.search-filter-btn) {
20
+ .search_filter_btn {
21
21
  background-color: #ffffff !important;
22
22
  border: 1px solid #e8e9ee !important;
23
23
  width: 10.4375rem;
@@ -30,6 +30,10 @@
30
30
  color: #000000;
31
31
  }
32
32
 
33
+ &:hover {
34
+ color: #000;
35
+ }
36
+
33
37
  svg {
34
38
  margin-left: 0.5rem;
35
39
  }
@@ -55,13 +59,16 @@
55
59
  }
56
60
  }
57
61
 
58
- :global(.api-btn) {
62
+ .api_btn {
59
63
  background-color: #ffffff !important;
64
+ display: flex;
65
+ flex-direction: row;
66
+ align-items: center;
60
67
  border: none !important;
61
68
  box-shadow: 0px 1px 2px rgba(16, 24, 40, 0.05);
62
69
  padding: 0.4rem;
63
- width: 8.5rem;
64
- font-size: 0.9175rem;
70
+ width: 8.4875rem;
71
+ font-size: 0.8125rem;
65
72
  font-weight: 400;
66
73
  line-height: 1.234rem;
67
74
  height: 2.25rem;
@@ -135,12 +142,78 @@
135
142
  cursor: pointer;
136
143
  }
137
144
 
145
+ .name-input {
146
+ // border-color: #bbbec5 !important;
147
+ width: 27.875rem;
148
+ height: 2.5rem;
149
+ border-radius: 0.5rem;
150
+ border: 0.0625rem solid #bbbec5;
151
+ padding-top: 0.5rem;
152
+ padding-bottom: 0.5rem;
153
+
154
+ > div.inputWrapper {
155
+ border: 0px !important;
156
+ }
157
+ }
158
+
159
+ .methodList {
160
+ width: 27.875rem;
161
+ border-radius: 0.5rem;
162
+ border: 0.0625rem solid #f0f1f2;
163
+
164
+ .method-item {
165
+ display: flex;
166
+ flex-direction: row;
167
+ justify-content: flex-start;
168
+ align-items: center;
169
+ gap: 0.5rem;
170
+ padding-left: 0.75rem;
171
+ padding-right: 0.75rem;
172
+ padding-top: 0.5rem;
173
+ border-radius: 0.5rem;
174
+ padding-bottom: 0.5rem;
175
+ border-bottom: 1px solid #f0f1f2;
176
+ span {
177
+ font-weight: 400;
178
+ font-size: 0.875rem;
179
+ }
180
+ input {
181
+ cursor: pointer;
182
+ width: 1.25rem;
183
+ height: 1.25rem;
184
+ border-radius: 0.25rem;
185
+ border: 1px solid #64748b;
186
+ }
187
+ }
188
+ }
189
+
138
190
  .method-container {
139
191
  display: flex;
140
192
  flex-direction: column;
141
193
  gap: 0.5rem;
142
194
  position: relative;
143
195
  z-index: 10;
196
+
197
+ .typeDdl {
198
+ cursor: pointer;
199
+ width: 27.875rem;
200
+ height: 2.5rem;
201
+ border-radius: 0.5rem;
202
+ border: 0.0625rem solid #bbbec5;
203
+ padding-top: 0.5rem;
204
+ padding-bottom: 0.5rem;
205
+ padding-left: 1.3rem;
206
+ padding-right: 0.75rem;
207
+ display: flex;
208
+ justify-content: space-between;
209
+ align-items: center;
210
+
211
+ span {
212
+ font-weight: 400;
213
+ font-size: 0.875rem;
214
+ color: #8390a2;
215
+ }
216
+ }
144
217
  }
145
218
 
146
219
  .method-container label {
@@ -157,7 +230,7 @@
157
230
  display: flex;
158
231
  justify-content: center;
159
232
  width: 100%;
160
- margin-top: auto;
233
+ padding-top: 0 !important;
161
234
  padding: 1.5rem 0;
162
235
  }
163
236
 
@@ -1,16 +1,31 @@
1
1
  import React, { useState, useRef } from 'react'
2
2
  import { Button, Size, Input, SelectGroup } from 'digitinary-ui'
3
3
  import SVGLoader from '../../../components/SVGLoader/SVGLoader'
4
- import { FilterIcon, BookIcon, ApiIcon, SearchIcon } from '../../../assets/icons'
4
+ import {
5
+ FilterIcon,
6
+ BookIcon,
7
+ ApiIcon,
8
+ SearchIcon,
9
+ arrowDownGray,
10
+ UpArrowIcon,
11
+ DownArrowIcon,
12
+ } from '../../../assets/icons'
5
13
  import Tooltip from '../../../components/Tooltip/Tooltip'
6
14
  import CommonDialog from '../../../components/dialog/index'
7
15
  import { METHOD_OPTIONS } from '../../../constants/methods.constant'
8
16
  import styles from './DocsHeader.module.scss'
9
17
 
10
- const DocsHeader: React.FC = () => {
18
+ const DocsHeader: React.FC = ({
19
+ transformedOpenApis,
20
+ updateFilteredData,
21
+ }: {
22
+ transformedOpenApis: any[]
23
+ updateFilteredData: any
24
+ }) => {
11
25
  const [showSearchFilter, setShowSearchFilter] = useState<boolean>(false)
12
26
  const [apiName, setApiName] = useState<string>('')
13
27
  const [selectedMethods, setSelectedMethods] = useState<any[]>([])
28
+ const [methodListOpened, setMethodListOpened] = useState(false)
14
29
  const [isMethodDropdownOpen, setIsMethodDropdownOpen] = useState<boolean>(false)
15
30
  const selectRef = useRef<any>(null)
16
31
 
@@ -24,9 +39,49 @@ const DocsHeader: React.FC = () => {
24
39
  }
25
40
 
26
41
  const handleApplyFilters = (): void => {
42
+ // Reset: no filters applied
43
+ if (!apiName?.trim() && (!selectedMethods || selectedMethods.length === 0)) {
44
+ updateFilteredData(transformedOpenApis, true)
45
+ setShowSearchFilter(false)
46
+ return
47
+ }
48
+
49
+ let filteredItems = [...transformedOpenApis]
50
+
51
+ // Filter by API name
52
+ if (apiName?.trim()) {
53
+ const lowerApiName = apiName.toLowerCase()
54
+ filteredItems = filteredItems.filter((api) => api.title.toLowerCase().includes(lowerApiName))
55
+ }
56
+
57
+ // Filter by selected HTTP methods
58
+ if (selectedMethods?.length) {
59
+ filteredItems = filteredItems.filter((api) => {
60
+ const allMethods = Object.values(api.tags || {})
61
+ .flat()
62
+ .map((endpoint: any) => endpoint.method?.toLowerCase())
63
+
64
+ return selectedMethods.some((method) => allMethods.includes(method.toLowerCase()))
65
+ })
66
+ }
67
+
68
+ updateFilteredData(filteredItems)
27
69
  setShowSearchFilter(false)
28
70
  }
29
71
 
72
+ const handleCheckMethod = (e, method: (typeof METHOD_OPTIONS)[0]) => {
73
+ const {
74
+ target: { checked },
75
+ } = e
76
+ if (checked) {
77
+ setSelectedMethods((prev) => [...prev, method.value])
78
+ } else {
79
+ if (selectedMethods.includes(method.value)) {
80
+ setSelectedMethods((prev) => prev.filter((_m) => _m != method.value))
81
+ }
82
+ }
83
+ }
84
+
30
85
  return (
31
86
  <>
32
87
  <header className={styles.api_docs_header}>
@@ -34,7 +89,7 @@ const DocsHeader: React.FC = () => {
34
89
  <Button
35
90
  variant="outlined"
36
91
  size="small"
37
- className="search-filter-btn"
92
+ className={styles.search_filter_btn}
38
93
  onClick={handleOpenSearchFilter}
39
94
  >
40
95
  Search & Filter
@@ -52,9 +107,8 @@ const DocsHeader: React.FC = () => {
52
107
  GUIDES
53
108
  </Button>
54
109
  </Tooltip>
55
- <Button variant="outlined" size="small" className="api-btn">
56
- <SVGLoader src={ApiIcon} />
57
- API reference
110
+ <Button variant="outlined" size="small" className={styles.api_btn}>
111
+ <SVGLoader src={ApiIcon} /> &nbsp; API reference
58
112
  </Button>
59
113
  </div>
60
114
  </div>
@@ -65,12 +119,14 @@ const DocsHeader: React.FC = () => {
65
119
  onClose={handleCloseSearchFilter}
66
120
  icon={false}
67
121
  withClose={false}
122
+ noActions
68
123
  content={
69
124
  <div className={`search-filter-form ${isMethodDropdownOpen ? 'expanded' : ''}`}>
70
125
  <div className="search-filter-form__header">
71
126
  <p className="search-filter-form__header__title">Search & Filter</p>
72
127
  </div>
73
128
  <Input
129
+ className="name-input"
74
130
  placeholder="Search by API name"
75
131
  value={apiName}
76
132
  onChange={(value) => setApiName(value as string)}
@@ -80,23 +136,37 @@ const DocsHeader: React.FC = () => {
80
136
  />
81
137
  <div className="method-container">
82
138
  <label>Method</label>
83
- <SelectGroup
139
+ {/* <SelectGroup
84
140
  isMultiple={true}
85
141
  size={Size.Medium}
86
142
  placeholder="Select Method"
87
143
  value={selectedMethods}
88
144
  onChange={(value) => setSelectedMethods(value || [])}
89
145
  options={[
90
- {
91
- list: METHOD_OPTIONS.map((method) => ({
92
- label: <span style={{ color: method.color }}>{method.label}</span>,
93
- value: method.value,
94
- data: method,
95
- })),
96
- },
146
+
97
147
  ]}
148
+ withSearch={false}
98
149
  className="method-select custom-select-border"
99
- />
150
+ /> */}
151
+ <div className="typeDdl" onClick={() => setIsMethodDropdownOpen((prev) => !prev)}>
152
+ <span>Select Method</span>
153
+ <SVGLoader src={!isMethodDropdownOpen ? DownArrowIcon : UpArrowIcon} />
154
+ </div>
155
+ {isMethodDropdownOpen && (
156
+ <div className="methodList">
157
+ {METHOD_OPTIONS.map((_m) => (
158
+ <div className="method-item">
159
+ <input
160
+ type="checkbox"
161
+ className="agreement-checkbox"
162
+ checked={selectedMethods.includes(_m.value)}
163
+ onChange={(e) => handleCheckMethod(e, _m)}
164
+ />
165
+ <span style={{ color: _m.color }}>{_m.label}</span>
166
+ </div>
167
+ ))}
168
+ </div>
169
+ )}
100
170
  </div>
101
171
  <div className="button-container">
102
172
  <Button
@@ -1,28 +1,60 @@
1
1
  import './style.scss'
2
- import React, { useState } from 'react'
2
+ import React, { useEffect, useState } from 'react'
3
3
  import SVGLoader from '../../../components/SVGLoader/SVGLoader'
4
4
  import { arrowDownGray, arrowRightGray, document, eye } from '../../../assets/icons'
5
+ import { EndpointData, OverviewData } from 'src/layout/docsLayout'
5
6
 
6
7
  const DocsSideMenuTree = ({
7
8
  apis,
8
9
  setActiveItemData,
10
+ activeItemData,
11
+ activeType,
12
+ expandedSections,
13
+ setExpandedSections,
9
14
  isFirstApiExpanded,
10
15
  setIsFirstApiExpanded,
16
+ setActiveType,
17
+ }: {
18
+ apis: OverviewData[]
19
+ setActiveItemData: React.Dispatch<React.SetStateAction<OverviewData | EndpointData>>
20
+ activeItemData: OverviewData | EndpointData
21
+ expandedSections: Record<string, boolean>
22
+ setExpandedSections: React.Dispatch<React.SetStateAction<Record<string, boolean>>>
23
+ isFirstApiExpanded: boolean
24
+ setIsFirstApiExpanded: React.Dispatch<React.SetStateAction<boolean>>
25
+ setActiveType: React.Dispatch<React.SetStateAction<'OVERVIEW' | 'ENDPOINT'>>
26
+ activeType: 'OVERVIEW' | 'ENDPOINT'
11
27
  }) => {
12
- const [expandedSections, setExpandedSections] = useState({})
28
+ // Auto-expand first API only once
29
+ useEffect(() => {
30
+ if (!apis?.length || !isFirstApiExpanded) return
31
+
32
+ const firstApi = apis[0]
33
+ const sectionKey = `api-${firstApi.apiSpecId}-section`
34
+ const overviewKey = `api-${firstApi.apiSpecId}-overview`
35
+
36
+ setExpandedSections((prev) => ({
37
+ ...prev,
38
+ [sectionKey]: true,
39
+ [overviewKey]: true,
40
+ }))
41
+
42
+ setActiveItemData(firstApi)
43
+ setActiveType('OVERVIEW')
44
+ setIsFirstApiExpanded(false)
45
+ }, [apis, isFirstApiExpanded])
13
46
 
14
47
  const toggleSection = (apiId, sectionId: string, resetOthers?: boolean, key?: string[]) => {
15
- isFirstApiExpanded && setIsFirstApiExpanded(false)
16
48
  if (resetOthers && key) {
17
49
  const filteredExpandedSections = Object.fromEntries(
18
- Object.entries({ ...expandedSections }).filter(([expandKey, _]) => {
50
+ Object.entries({ ...expandedSections }).filter(([expandKey]) => {
19
51
  // Close other APIs sections
20
52
  if (!expandKey.includes(apiId)) return false
21
53
  // always return the clicked on section
22
- else if (expandKey === sectionId) return true
54
+ if (expandKey === sectionId) return true
23
55
  // filter all sections containing the key
24
- else if (key.some((k) => expandKey.includes(k))) return false
25
- else return true
56
+ if (key.some((k) => expandKey.includes(k))) return false
57
+ return true
26
58
  })
27
59
  )
28
60
 
@@ -38,64 +70,94 @@ const DocsSideMenuTree = ({
38
70
  }
39
71
  }
40
72
 
41
- const renderEndpoints = (endpoints, api) => {
42
- return endpoints.map((endpoint, index) => {
43
- const isResourceExpanded = expandedSections[`api-${api.id}-resource-${endpoint.id}`]
73
+ const renderEndpoints = (endpoints: EndpointData[], api: OverviewData) =>
74
+ endpoints.map((endpoint, index) => {
75
+ const key = `api-${api.apiSpecId}-resource-${endpoint.id}`
76
+ const isExpanded = expandedSections[key]
44
77
 
45
78
  return (
46
79
  <div
47
80
  key={index}
48
81
  className={`api-docs-api-tree__endpoint api-docs-api-tree__endpoint--${endpoint.method.toLowerCase()}`}
49
82
  onClick={() => {
50
- setActiveItemData({
51
- ...endpoint,
52
- api: {
53
- id: api.id,
54
- title: api.title,
55
- description: api.description,
56
- version: api.version,
57
- },
58
- })
59
-
60
- if (!isResourceExpanded) {
61
- toggleSection(api.id, `api-${api.id}-resource-${endpoint.id}`, true, [
62
- 'resource',
63
- 'overview',
64
- ])
83
+ if (!isExpanded) {
84
+ setActiveItemData({
85
+ ...endpoint,
86
+ api: {
87
+ id: api.apiSpecId,
88
+ title: api.title,
89
+ description: api.description,
90
+ version: api.version,
91
+ ...api,
92
+ },
93
+ })
94
+ setActiveType('ENDPOINT')
95
+ toggleSection(api.apiSpecId, key, true, ['resource', 'overview'])
65
96
  }
66
97
  }}
67
- data-active={isResourceExpanded}
98
+ data-active={isExpanded}
68
99
  >
69
100
  <span className="api-docs-api-tree__endpoint-method">{endpoint.method}</span>
70
101
  <span className="api-docs-api-tree__endpoint-name">{endpoint.path}</span>
71
102
  </div>
72
103
  )
73
104
  })
74
- }
75
105
 
76
- const renderApiSection = (api, index) => {
77
- const isApiExpanded = expandedSections[`api-${api.id}-section`]
78
- const isEndpointActive = Object.keys(expandedSections).some((k) =>
79
- k.includes(`api-${api.id}-resource`)
106
+ const renderSubSection = (
107
+ tagName: string,
108
+ data: EndpointData[],
109
+ api: OverviewData,
110
+ sectionIndex: number
111
+ ) => {
112
+ const sectionKey = `api-${api.apiSpecId}-section-${sectionIndex}`
113
+ const isSectionExpanded = expandedSections[sectionKey]
114
+
115
+ return (
116
+ <div key={sectionKey} className="api-docs-api-tree__subsection">
117
+ <div
118
+ className="api-docs-api-tree__subsection-header"
119
+ onClick={() => toggleSection(api.apiSpecId, sectionKey)}
120
+ >
121
+ {isSectionExpanded ? (
122
+ <SVGLoader src={arrowDownGray} />
123
+ ) : (
124
+ <SVGLoader src={arrowRightGray} />
125
+ )}
126
+ <span className="api-docs-api-tree__subsection-title">{tagName}</span>
127
+ </div>
128
+
129
+ {isSectionExpanded && (
130
+ <div className="api-docs-api-tree__endpoints">{renderEndpoints(data, api)}</div>
131
+ )}
132
+ </div>
80
133
  )
81
- const isEndpointsExpanded = expandedSections[`api-${api.id}-endpoints`]
82
- const isOverviewExpanded = expandedSections[`api-${api.id}-overview`]
134
+ }
83
135
 
84
- if (isFirstApiExpanded && index === 0 && !isApiExpanded) {
85
- toggleSection(api.id, `api-${api.id}-section`)
86
- toggleSection(api.id, `api-${api.id}-overview`)
87
- setActiveItemData(api)
88
- }
136
+ const renderApiSection = (api: OverviewData) => {
137
+ const sectionKey = `api-${api.apiSpecId}-section`
138
+ const endpointsKey = `api-${api.apiSpecId}-endpoints`
139
+ const overviewKey = `api-${api.apiSpecId}-overview`
140
+
141
+ const isApiExpanded = expandedSections[sectionKey]
142
+ const isOverviewExpanded =
143
+ 'apiSpecId' in activeItemData &&
144
+ activeItemData.apiSpecId === api.apiSpecId &&
145
+ activeType === 'OVERVIEW'
146
+ const isEndpointActive =
147
+ 'api' in activeItemData &&
148
+ activeItemData.api.id === api.apiSpecId &&
149
+ 'path' in activeItemData &&
150
+ 'method' in activeItemData
89
151
 
90
152
  return (
91
153
  <div
92
- key={api.id}
154
+ key={api.apiSpecId}
93
155
  className="api-docs-api-tree__section"
94
156
  data-active={isEndpointActive || isOverviewExpanded}
95
157
  >
96
158
  <div
97
159
  className="api-docs-api-tree__section-header"
98
- onClick={() => toggleSection(api.id, `api-${api.id}-section`)}
160
+ onClick={() => toggleSection(api.apiSpecId, sectionKey)}
99
161
  >
100
162
  {isApiExpanded ? <SVGLoader src={arrowDownGray} /> : <SVGLoader src={arrowRightGray} />}
101
163
  <SVGLoader src={document} />
@@ -105,39 +167,40 @@ const DocsSideMenuTree = ({
105
167
  {isApiExpanded && (
106
168
  <>
107
169
  <div
108
- className={`api-docs-api-tree__section__overview`}
170
+ className="api-docs-api-tree__section__overview"
109
171
  onClick={() => {
110
- toggleSection(api.id, `api-${api.id}-overview`, true, ['resource'])
111
- setActiveItemData(api)
172
+ if (!isOverviewExpanded) {
173
+ toggleSection(api.apiSpecId, overviewKey, true, ['resource'])
174
+ setActiveItemData(api)
175
+ setActiveType('OVERVIEW')
176
+ }
112
177
  }}
113
178
  data-active={isOverviewExpanded}
114
179
  >
115
- {<SVGLoader src={eye} />}
180
+ <SVGLoader src={eye} />
116
181
  <span>Overview</span>
117
182
  </div>
183
+
118
184
  <div
119
185
  className="api-docs-api-tree__section__endpoints"
120
- onClick={() => {
121
- toggleSection(api.id, `api-${api.id}-endpoints`)
122
- }}
186
+ onClick={() => toggleSection(api.apiSpecId, endpointsKey)}
123
187
  data-active={isEndpointActive && !isOverviewExpanded}
124
188
  >
125
- {isEndpointsExpanded ? (
189
+ {expandedSections[endpointsKey] ? (
126
190
  <SVGLoader src={arrowDownGray} />
127
191
  ) : (
128
192
  <SVGLoader src={arrowRightGray} />
129
193
  )}
130
194
  <span>Endpoints</span>
131
195
  </div>
132
- {isEndpointsExpanded && (
196
+
197
+ {expandedSections[endpointsKey] && (
133
198
  <div className="api-docs-api-tree__subsections">
134
199
  {Object.entries(api.tags)
135
- .sort(([a], [b]) => {
136
- if (a === 'default') return 1
137
- if (b === 'default') return -1
138
- return a.localeCompare(b)
139
- })
140
- .map(([tagName, data], index) => renderSubSection(tagName, data, api, index))}
200
+ .sort(([a], [b]) =>
201
+ a === 'default' ? 1 : b === 'default' ? -1 : a.localeCompare(b)
202
+ )
203
+ .map(([tagName, data], i) => renderSubSection(tagName, data, api, i))}
141
204
  </div>
142
205
  )}
143
206
  </>
@@ -146,38 +209,7 @@ const DocsSideMenuTree = ({
146
209
  )
147
210
  }
148
211
 
149
- const renderSubSection = (tagName, data, api, sectionIndex) => {
150
- const sectionKey = `api-${api.id}-section-${sectionIndex}`
151
- const isSectionExpanded = expandedSections[sectionKey]
152
-
153
- return (
154
- <div key={sectionKey} className="api-docs-api-tree__subsection">
155
- <>
156
- <div
157
- className="api-docs-api-tree__subsection-header"
158
- onClick={() => toggleSection(api.id, sectionKey)}
159
- >
160
- {isSectionExpanded ? (
161
- <SVGLoader src={arrowDownGray} />
162
- ) : (
163
- <SVGLoader src={arrowRightGray} />
164
- )}
165
- <span className="api-docs-api-tree__subsection-title">{tagName}</span>
166
- </div>
167
-
168
- {isSectionExpanded && (
169
- <div className="api-docs-api-tree__endpoints">{renderEndpoints(data, api)}</div>
170
- )}
171
- </>
172
- </div>
173
- )
174
- }
175
-
176
- return (
177
- <aside className="api-docs-api-tree">
178
- {apis.map((api, index) => renderApiSection(api, index))}
179
- </aside>
180
- )
212
+ return <aside className="api-docs-api-tree">{apis.map((api) => renderApiSection(api))}</aside>
181
213
  }
182
214
 
183
215
  export default DocsSideMenuTree
@@ -1,10 +1,12 @@
1
1
  .api-docs-layout {
2
+ @import url('https://fonts.googleapis.com/css2?family=Cascadia+Code:ital,wght@0,200..700;1,200..700&display=swap');
3
+
2
4
  display: grid;
3
5
  height: 100vh;
4
6
  max-height: 100%;
5
7
  width: 100%;
6
8
  overflow: hidden;
7
- grid-template: 3.125rem auto / 12.5rem 1fr auto;
9
+ grid-template: 2.625rem auto / 12.5rem 1fr auto;
8
10
  padding: 0 !important;
9
11
 
10
12
  * {