@scalar/api-client 0.1.21 → 0.2.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.
Files changed (66) hide show
  1. package/dist/components/ApiClient/Request/RequestBody.vue.d.ts +0 -6
  2. package/dist/components/ApiClient/Request/RequestBody.vue.d.ts.map +1 -1
  3. package/dist/components/ApiClient/Response/ResponseHeaders.vue.d.ts.map +1 -1
  4. package/dist/components/CodeMirror/CodeMirror.vue.d.ts.map +1 -1
  5. package/dist/components/SimpleTable/SimpleCell.vue.d.ts.map +1 -1
  6. package/dist/components/SimpleTable/SimpleHeader.vue.d.ts.map +1 -1
  7. package/dist/components/SimpleTable/SimpleRow.vue.d.ts.map +1 -1
  8. package/dist/components/SimpleTable/SimpleTable.vue.d.ts.map +1 -1
  9. package/dist/fixtures/index.d.ts +1 -1
  10. package/dist/fixtures/index.d.ts.map +1 -1
  11. package/dist/helpers/sendRequest.d.ts.map +1 -1
  12. package/dist/index.js +98 -60
  13. package/package.json +7 -9
  14. package/src/components/ApiClient/AddressBar.vue +462 -0
  15. package/src/components/ApiClient/ApiClient.vue +266 -0
  16. package/src/components/ApiClient/Request/Request.vue +271 -0
  17. package/src/components/ApiClient/Request/RequestAuth.vue +221 -0
  18. package/src/components/ApiClient/Request/RequestBody.vue +39 -0
  19. package/src/components/ApiClient/Request/RequestHeaders.vue +24 -0
  20. package/src/components/ApiClient/Request/RequestQuery.vue +25 -0
  21. package/src/components/ApiClient/Request/RequestVariables.vue +25 -0
  22. package/src/components/ApiClient/Request/index.ts +1 -0
  23. package/src/components/ApiClient/RequestHistory.vue +114 -0
  24. package/src/components/ApiClient/RequestHistoryItem.vue +59 -0
  25. package/src/components/ApiClient/Response/Copilot.vue.bak +385 -0
  26. package/src/components/ApiClient/Response/Response.vue +120 -0
  27. package/src/components/ApiClient/Response/ResponseBody.vue +23 -0
  28. package/src/components/ApiClient/Response/ResponseHeaders.vue +52 -0
  29. package/src/components/ApiClient/Response/ResponseMetaInformation.vue +58 -0
  30. package/src/components/ApiClient/Response/index.ts +1 -0
  31. package/src/components/ApiClient/index.ts +1 -0
  32. package/src/components/CodeMirror/CodeMirror.vue +232 -0
  33. package/src/components/CodeMirror/extensions/variables.ts +41 -0
  34. package/src/components/CodeMirror/index.ts +1 -0
  35. package/src/components/CollapsibleSection/CollapsibleSection.vue +149 -0
  36. package/src/components/CollapsibleSection/index.ts +1 -0
  37. package/src/components/FlowModal.vue +133 -0
  38. package/src/components/Grid/Grid.vue +511 -0
  39. package/src/components/Grid/SimpleGrid.vue +33 -0
  40. package/src/components/Grid/index.ts +2 -0
  41. package/src/components/HelpfulLink.vue +19 -0
  42. package/src/components/SimpleTable/SimpleCell.vue +47 -0
  43. package/src/components/SimpleTable/SimpleHeader.vue +17 -0
  44. package/src/components/SimpleTable/SimpleRow.vue +14 -0
  45. package/src/components/SimpleTable/SimpleTable.vue +13 -0
  46. package/src/components/SimpleTable/index.ts +4 -0
  47. package/src/fixtures/httpHeaders.ts +530 -0
  48. package/src/fixtures/httpStatusCodes.ts +259 -0
  49. package/src/fixtures/index.ts +6 -0
  50. package/src/helpers/createPlaceholderRequest.ts +16 -0
  51. package/src/helpers/generateParameters.ts +19 -0
  52. package/src/helpers/generateRequest.ts +26 -0
  53. package/src/helpers/index.ts +5 -0
  54. package/src/helpers/mapFromArray.ts +16 -0
  55. package/src/helpers/sendRequest.ts +94 -0
  56. package/src/hooks/index.ts +2 -0
  57. package/src/hooks/useCopilot.ts +64 -0
  58. package/src/hooks/useOperation.test.ts +7 -0
  59. package/src/hooks/useOperation.ts +43 -0
  60. package/src/index.ts +9 -0
  61. package/src/stores/apiClientRequestStore.ts +103 -0
  62. package/src/stores/apiClientStore.ts +57 -0
  63. package/src/stores/index.ts +5 -0
  64. package/src/types.ts +181 -0
  65. package/dist/index2.js +0 -4
  66. package/dist/style.css +0 -1550
@@ -0,0 +1,114 @@
1
+ <script setup lang="ts">
2
+ import { useApiClientRequestStore } from '../../stores/apiClientRequestStore'
3
+ import RequestHistoryItem from './RequestHistoryItem.vue'
4
+
5
+ defineEmits<{
6
+ (e: 'toggle'): void
7
+ }>()
8
+
9
+ const { requestHistoryOrder } = useApiClientRequestStore()
10
+ </script>
11
+ <template>
12
+ <div class="navigation-content-item">
13
+ <div class="navtable">
14
+ <div class="navtable-table">
15
+ <div class="navtable-item navtable-item__top">
16
+ <div class="navtable-item-40">
17
+ <label for="">Request</label>
18
+ </div>
19
+ <div class="navtable-item-40">
20
+ <label for="">Response</label>
21
+ </div>
22
+ <div class="navtable-item-20">
23
+ <label for="">TIME</label>
24
+ </div>
25
+ </div>
26
+ <div class="navtable-radios">
27
+ <RequestHistoryItem
28
+ v-for="history in requestHistoryOrder"
29
+ :key="history"
30
+ :history="history" />
31
+ </div>
32
+ <div class="navtable-mock">
33
+ <div class="navtable-item">
34
+ <div class="navtable-item-40" />
35
+ <div class="navtable-item-40" />
36
+ <div class="navtable-item-20" />
37
+ </div>
38
+ </div>
39
+ </div>
40
+ </div>
41
+ </div>
42
+ </template>
43
+
44
+ <style>
45
+ .navtable-mock {
46
+ background-repeat: repeat;
47
+ width: 100%;
48
+ background-image: linear-gradient(
49
+ 0deg,
50
+ var(--theme-border-color) 1px,
51
+ --theme-background-1 1px
52
+ );
53
+ background-size: 31px 31px;
54
+ background-position: center 1px;
55
+ flex: 1;
56
+ position: relative;
57
+ }
58
+ .navtable-mock .navtable-item {
59
+ position: absolute;
60
+ width: 100%;
61
+ height: 100%;
62
+ left: 0;
63
+ top: 0;
64
+ background: transparent;
65
+ border-top: none;
66
+ }
67
+
68
+ .radio {
69
+ height: 16px;
70
+ width: 16px;
71
+ background: transparent;
72
+ border: var(--border);
73
+ flex-shrink: 0;
74
+ margin-right: 6px;
75
+ margin-left: 4px;
76
+ border-radius: 50%;
77
+ display: flex;
78
+ align-items: center;
79
+ justify-content: center;
80
+ outline: none;
81
+ }
82
+ .radio:before {
83
+ content: '';
84
+ position: absolute;
85
+ top: 0;
86
+ left: 0;
87
+ width: 100%;
88
+ height: 100%;
89
+ cursor: pointer;
90
+ }
91
+ .navtable-item__active .radio:after {
92
+ content: '';
93
+ width: 5px;
94
+ height: 8px;
95
+ border: solid white;
96
+ border-width: 0 1.5px 1.5px 0;
97
+ transform: rotate(45deg) translate3d(-0.5px, -1px, 0);
98
+ }
99
+ .radio.post {
100
+ background: var(--theme-post-color);
101
+ }
102
+ .radio.delete {
103
+ background: var(--theme-delete-color);
104
+ }
105
+ .radio.patch {
106
+ background: var(--theme-patch-color);
107
+ }
108
+ .radio.get {
109
+ background: var(--theme-get-color);
110
+ }
111
+ .radio.put {
112
+ background: var(--theme-put-color);
113
+ }
114
+ </style>
@@ -0,0 +1,59 @@
1
+ <script setup lang="ts">
2
+ import TimeAgo from 'javascript-time-ago'
3
+ import en from 'javascript-time-ago/locale/en'
4
+ import prettyBytes from 'pretty-bytes'
5
+ import prettyMilliseconds from 'pretty-ms'
6
+
7
+ import { useApiClientRequestStore } from '../../stores/apiClientRequestStore'
8
+ import { type ClientResponse } from '../../types'
9
+
10
+ defineProps<{ history: string }>()
11
+ TimeAgo.addLocale(en)
12
+ const timeAgo = new TimeAgo('en-US')
13
+
14
+ const { requestHistory, activeRequestId, setActiveResponse } =
15
+ useApiClientRequestStore()
16
+
17
+ const getContentLength = (response: ClientResponse) => {
18
+ if (response?.headers?.['X-API-Client-Content-Length']) {
19
+ return prettyBytes(
20
+ parseFloat(response.headers['X-API-Client-Content-Length']),
21
+ )
22
+ }
23
+ return prettyBytes(0)
24
+ }
25
+ </script>
26
+ <template>
27
+ <div
28
+ class="navtable-item"
29
+ :class="{ 'navtable-item__active': activeRequestId === history }"
30
+ @click="setActiveResponse(history)">
31
+ <div class="navtable-item-40 navtable-item-request">
32
+ <button
33
+ class="radio"
34
+ :class="requestHistory[history].request.type.toLowerCase()"
35
+ type="button" />
36
+ <span>
37
+ <em>{{ requestHistory[history].request.type }}</em>
38
+ {{ requestHistory[history].request.url }}
39
+ </span>
40
+ </div>
41
+ <div class="navtable-item-40 navtable-item-response">
42
+ <span>{{
43
+ prettyMilliseconds(requestHistory[history].response.duration)
44
+ }}</span>
45
+ <span
46
+ :class="`scalar-api-client__status--${String(
47
+ requestHistory[history].response.statusCode,
48
+ ).charAt(0)}xx`">
49
+ {{ requestHistory[history].response.statusCode }}
50
+ </span>
51
+ <span>{{ getContentLength(requestHistory[history].response) }}</span>
52
+ </div>
53
+ <div class="navtable-item-20 navtable-item-time">
54
+ <span>
55
+ {{ timeAgo.format(requestHistory[history].sentTime) }}
56
+ </span>
57
+ </div>
58
+ </div>
59
+ </template>
@@ -0,0 +1,385 @@
1
+ <script setup lang="ts">
2
+ import { useMarkdown } from '@anc/library'
3
+ import { StarterKit } from '@tiptap/starter-kit'
4
+ import { Editor, EditorContent } from '@tiptap/vue-3'
5
+ import { Markdown } from 'tiptap-markdown'
6
+ import { computed, ref, watch } from 'vue'
7
+
8
+ import { CopilotLoadingStates, useCopilot } from '../../../hooks'
9
+
10
+ const content = ref('')
11
+ const editor = ref<any>()
12
+ const itemSuggestionOpen = ref(false)
13
+ const contentFilled = ref(false)
14
+
15
+ editor.value = new Editor({
16
+ editable: false,
17
+ extensions: [StarterKit],
18
+ })
19
+
20
+ const { html, setMarkdown } = useMarkdown(content, [StarterKit, Markdown])
21
+
22
+ const { state, onRecommendation, setLoadingState } = useCopilot()
23
+
24
+ onRecommendation((recommendation: string) => {
25
+ contentFilled.value = true
26
+ content.value += recommendation
27
+ setMarkdown(content.value)
28
+ setLoadingState(CopilotLoadingStates.Fix)
29
+ })
30
+
31
+ watch(html, () => {
32
+ editor.value.commands.setContent(html)
33
+ })
34
+
35
+ const classLookUp: Partial<Record<CopilotLoadingStates, string>> = {
36
+ [CopilotLoadingStates.Loading]: 'scalar-copilot__header-button--loading',
37
+ [CopilotLoadingStates.Working]: 'scalar-copilot__header-button--working',
38
+ [CopilotLoadingStates.Success]: 'scalar-copilot__header-button--success',
39
+ }
40
+
41
+ const loadingStateClass = computed(() => classLookUp[state.loadingState])
42
+
43
+ const toggleItemSuggestion = () => {
44
+ itemSuggestionOpen.value = !itemSuggestionOpen.value
45
+ }
46
+
47
+ const itemSuggestionState = computed(() => ({
48
+ 'scalar-copilot__suggestion--open': itemSuggestionOpen.value,
49
+ }))
50
+
51
+ const contentFilledState = computed(() => ({
52
+ 'scalar-copilot--inactive': !contentFilled.value,
53
+ }))
54
+
55
+ function sleep(ms: number) {
56
+ return new Promise((resolve) => setTimeout(resolve, ms))
57
+ }
58
+
59
+ const fixErrors = async () => {
60
+ setLoadingState(CopilotLoadingStates.Working)
61
+ await sleep(3000) // Sleep for 3 seconds
62
+ content.value = ''
63
+ setMarkdown(content.value)
64
+ setLoadingState(CopilotLoadingStates.Success)
65
+ contentFilled.value = false
66
+ }
67
+ </script>
68
+ <template>
69
+ <!-- remove class scalar-copilot--inactive once we start loading suggestions-->
70
+ <!-- add the class "scalar-copilot__response" when copilot is within response -->
71
+ <div
72
+ class="scalar-copilot"
73
+ :class="contentFilledState">
74
+ <div class="scalar-copilot__header">
75
+ <span>
76
+ <svg
77
+ fill="none"
78
+ height="48"
79
+ stroke-width="2"
80
+ viewBox="0 0 24 24"
81
+ width="48"
82
+ xmlns="http://www.w3.org/2000/svg">
83
+ <path
84
+ d="M16.625 13.724c-4.988 1.68-6.632 3.552-7.848 8.213-1.216-4.66-2.86-6.532-7.848-8.213 4.988-1.68 6.632-3.552 7.848-8.214 1.216 4.662 2.86 6.533 7.848 8.214ZM22.813 5.948c-2.814.944-3.741 1.996-4.427 4.615-.686-2.619-1.614-3.67-4.427-4.615 2.813-.944 3.74-1.996 4.427-4.615.686 2.62 1.613 3.67 4.427 4.615ZM23.178 19.562c-2.082.684-2.769 1.446-3.276 3.344-.508-1.898-1.195-2.66-3.277-3.344 2.082-.684 2.769-1.446 3.277-3.344.507 1.898 1.194 2.66 3.276 3.344Z"
85
+ stroke="currentColor"
86
+ stroke-linecap="round"
87
+ stroke-linejoin="round" />
88
+ </svg>
89
+ AI Suggestions
90
+ </span>
91
+ <!-- Add this class: "scalar-copilot__header-button--loading" when you blur an input and are loading to check for errors -->
92
+ <div
93
+ v-if="state.loadingState !== CopilotLoadingStates.Inactive"
94
+ class="scalar-copilot__header-button"
95
+ :class="loadingStateClass"
96
+ @click="fixErrors">
97
+ <!--should be applied to the tag above-->
98
+ Fix (1) Error
99
+ </div>
100
+ <!-- Add this class: "scalar-copilot__header-button--working" after you click button -->
101
+ <!-- Add this class: "scalar-copilot__header-button--success" after button is done working add the success -->
102
+ <!-- class IF there is no more errors to fix IF there is still errors to fix don't add -->
103
+ </div>
104
+ <div
105
+ v-if="contentFilled"
106
+ class="scalar-copilot__item">
107
+ <div
108
+ class="scalar-copilot__suggestion"
109
+ :class="itemSuggestionState">
110
+ <!-- when you click toggle you need to add and remove the class "scalar-copilot__suggestion--open" to the div above it-->
111
+ <div
112
+ class="scalar-copilot__item__toggle"
113
+ @click="toggleItemSuggestion">
114
+ <div class="scalar-copilot__item__toggle-button" />
115
+ </div>
116
+ <EditorContent
117
+ class="scalar-copilot__suggestion__content"
118
+ :editor="editor" />
119
+ </div>
120
+ <div class="scalar-copilot__item-check">
121
+ <label class="meta-check">
122
+ <input
123
+ checked
124
+ type="checkbox" />
125
+ <span class="meta-checkmark" />
126
+ </label>
127
+ </div>
128
+ </div>
129
+ </div>
130
+ </template>
131
+
132
+ <style scoped>
133
+ .scalar-copilot__response .scalar-copilot__header {
134
+ height: 0px;
135
+ min-height: 0px;
136
+ padding: 0;
137
+ border-bottom: 0;
138
+ }
139
+ .scalar-copilot__response .scalar-copilot__header span {
140
+ display: none;
141
+ }
142
+ .scalar-copilot__response .scalar-copilot__header-button {
143
+ position: absolute;
144
+ top: 8px;
145
+ right: 12px;
146
+ }
147
+ .scalar-copilot {
148
+ color: var(--theme-color-1);
149
+ width: 100%;
150
+ border-radius: var(--theme-radius-lg);
151
+ border: 1px solid var(--theme-border-color);
152
+ }
153
+ .scalar-copilot--inactive {
154
+ border: 1px solid transparent;
155
+ background: var(--theme-background-3);
156
+ }
157
+ .scalar-copilot__header {
158
+ padding: 7px 7px 7px 9px;
159
+ min-height: 32.5px;
160
+ display: flex;
161
+ color: var(--theme-color-disabled);
162
+ font-weight: var(--theme-bold);
163
+ align-items: center;
164
+ justify-content: space-between;
165
+ border-bottom: 1px solid var(--theme-border-color);
166
+ }
167
+ .scalar-copilot__header span {
168
+ display: flex;
169
+ align-items: center;
170
+ }
171
+ .scalar-copilot__header svg {
172
+ width: 12px;
173
+ height: 12px;
174
+ margin-right: 6px;
175
+ }
176
+ .scalar-copilot__item {
177
+ line-height: 1.45;
178
+ display: flex;
179
+ }
180
+ .scalar-copilot__item:not(:last-of-type) {
181
+ border-bottom: 1px solid var(--theme-border-color);
182
+ }
183
+ .scalar-copilot__suggestion {
184
+ position: relative;
185
+ cursor: pointer;
186
+ display: flex;
187
+ }
188
+ .scalar-copilot__suggestion__content {
189
+ -webkit-line-clamp: 2;
190
+ -webkit-box-orient: vertical;
191
+ overflow: hidden;
192
+ max-height: 52.8px;
193
+ display: -webkit-box;
194
+ padding: 9px 9px 9px 27px;
195
+ }
196
+ .scalar-copilot__suggestion__content:after {
197
+ content: '';
198
+ position: absolute;
199
+ bottom: 0;
200
+ left: 0;
201
+ width: 100%;
202
+ height: 9px;
203
+ background: var(--theme-background-2);
204
+ }
205
+ .scalar-copilot__suggestion--open .scalar-copilot__suggestion__content {
206
+ max-height: initial;
207
+ cursor: initial;
208
+ display: block;
209
+ }
210
+ .scalar-copilot__item-check {
211
+ border-left: 1px solid var(--theme-border-color);
212
+ width: 32.5px;
213
+ flex-shrink: 0;
214
+ display: flex;
215
+ align-items: center;
216
+ justify-content: center;
217
+ }
218
+ .scalar-copilot__header-button {
219
+ background: var(--scalar-api-client-color);
220
+ border-radius: var(--theme-radius-lg);
221
+ cursor: pointer;
222
+ flex-shrink: 0;
223
+ display: flex;
224
+ color: white;
225
+ padding: 2px 6px;
226
+ }
227
+ .dark-mode .scalar-copilot__header-button {
228
+ color: black;
229
+ }
230
+ .scalar-copilot__header-button--loading {
231
+ background: transparent;
232
+ font-size: 0px;
233
+ color: var(--theme-color-disabled);
234
+ }
235
+ .scalar-copilot__header-button--working {
236
+ font-size: 0px;
237
+ }
238
+ .scalar-copilot__header-button--working:before,
239
+ .scalar-copilot__header-button--loading:before {
240
+ content: '';
241
+ border: 1px solid var(--theme-color-disabled);
242
+ border-top: 1px solid var(--theme-color-1);
243
+ animation: urlloader 0.45s linear infinite;
244
+ background: transparent;
245
+ width: 14px;
246
+ height: 14px;
247
+ margin-left: 0;
248
+ margin-right: 9px;
249
+ border-radius: 50%;
250
+ display: block;
251
+ }
252
+ .scalar-copilot__header-button--working:before {
253
+ border: 1px solid rgba(255, 255, 255, 0.1);
254
+ border-top: 1px solid white;
255
+ }
256
+ .dark-mode .scalar-copilot__header-button--working:before {
257
+ border: 1px solid rgba(0, 0, 0, 0.15);
258
+ border-top: 1px solid black;
259
+ }
260
+ .scalar-copilot__header-button--working:after {
261
+ content: 'Working';
262
+ font-size: 12px;
263
+ }
264
+ .scalar-copilot__header-button--loading:after {
265
+ content: 'Loading';
266
+ font-size: 12px;
267
+ }
268
+ .scalar-copilot__header-button--success {
269
+ font-size: 0;
270
+ background: transparent;
271
+ cursor: default;
272
+ }
273
+ .scalar-copilot__header-button--success:after {
274
+ content: 'Success';
275
+ font-size: 12px;
276
+ color: var(--theme-color-2);
277
+ }
278
+ .scalar-copilot__header-button--success:before {
279
+ content: '';
280
+ display: block;
281
+ width: 5px;
282
+ height: 8px;
283
+ border: solid var(--theme-color-2);
284
+ margin-right: 9px;
285
+ top: 3px;
286
+ position: relative;
287
+ border-width: 0 1.5px 1.5px 0;
288
+ transform: rotate(45deg) translate3d(0, -1px, 0);
289
+ }
290
+ @keyframes urlloader {
291
+ 0% {
292
+ transform: rotate(0deg);
293
+ }
294
+ to {
295
+ transform: rotate(1turn);
296
+ }
297
+ }
298
+ .scalar-copilot__item__toggle {
299
+ position: absolute;
300
+ width: 100%;
301
+ height: 100%;
302
+ padding: 9px;
303
+ z-index: 10;
304
+ cursor: pointer;
305
+ }
306
+ .scalar-copilot__item__toggle-button {
307
+ width: 6px;
308
+ height: 6px;
309
+ margin-right: 12px;
310
+ flex-shrink: 0;
311
+ position: relative;
312
+ top: 5px;
313
+ left: -2px;
314
+ transform: rotate(315deg);
315
+ box-shadow: 1px 1px 0 var(--theme-color-disabled);
316
+ z-index: 10;
317
+ }
318
+ .scalar-copilot__item__toggle-button:after {
319
+ content: '';
320
+ width: 20px;
321
+ height: 20px;
322
+ border-radius: 50%;
323
+ position: absolute;
324
+ display: block;
325
+ left: -5px;
326
+ top: -4px;
327
+ }
328
+ .scalar-copilot__item__toggle-button:hover {
329
+ box-shadow: 1px 1px 0 var(--theme-color-1);
330
+ }
331
+ .scalar-copilot__suggestion--open .scalar-copilot__item__toggle-button {
332
+ transform: rotate(45deg);
333
+ left: 2px;
334
+ top: 1px;
335
+ }
336
+ .scalar-copilot__suggestion--open .scalar-copilot__item__toggle {
337
+ height: 24px;
338
+ position: absolute;
339
+ width: 24px;
340
+ }
341
+ .scalar-copilot__item__toggle:hover:after {
342
+ content: '';
343
+ background: var(--theme-background-3);
344
+ width: 20px;
345
+ height: 20px;
346
+ border-radius: 50%;
347
+ position: absolute;
348
+ left: 3px;
349
+ top: 7px;
350
+ z-index: 0;
351
+ }
352
+ .scalar-copilot__suggestion--open .scalar-copilot__item__toggle:hover:after {
353
+ top: 6px;
354
+ left: 4px;
355
+ }
356
+
357
+ .scalar-api-client__item:hover .scalar-copilot__item__toggle-button,
358
+ .scalar-api-client__item:focus-within .scalar-copilot__item__toggle-button {
359
+ opacity: 1;
360
+ }
361
+
362
+ .scalar-copilot__toggle-button {
363
+ appearance: none;
364
+ color: var(--scalar-api-client-color2);
365
+ font-size: var(--theme-small);
366
+ background: var(--scalar-api-client-gradient);
367
+ border-radius: var(--theme-radius-lg);
368
+ border: 1px solid var(--theme-border-color);
369
+ font-weight: var(--theme-bold);
370
+ max-height: 25px;
371
+ padding: 4px 8px;
372
+ outline: none;
373
+ cursor: pointer;
374
+ transition: opacity 0.15s ease-in-out;
375
+ white-space: nowrap;
376
+ &:hover {
377
+ color: var(--theme-color-1);
378
+ }
379
+ }
380
+
381
+ .scalar-copilot__toggle-button svg {
382
+ margin-left: 6px;
383
+ width: 8px;
384
+ }
385
+ </style>
@@ -0,0 +1,120 @@
1
+ <script setup lang="ts">
2
+ import { computed } from 'vue'
3
+
4
+ import { useApiClientRequestStore } from '../../../stores/apiClientRequestStore'
5
+ import { CollapsibleSection } from '../../CollapsibleSection'
6
+ // import Copilot from './Copilot.vue'
7
+ import { SimpleGrid } from '../../Grid'
8
+ import ResponseBody from './ResponseBody.vue'
9
+ import ResponseHeaders from './ResponseHeaders.vue'
10
+ import ResponseMetaInformation from './ResponseMetaInformation.vue'
11
+
12
+ const { activeResponse, activeRequestId } = useApiClientRequestStore()
13
+
14
+ // Headers
15
+ const responseHeaders = computed(() => {
16
+ const headers = activeResponse.value?.headers
17
+
18
+ return headers
19
+ ? Object.keys(headers)
20
+ .map((key) => ({ name: key, value: headers[key] }))
21
+ .filter(
22
+ (item) =>
23
+ ![
24
+ 'rest-api-client-content-length',
25
+ 'X-API-Client-Content-Length',
26
+ ].includes(item.name),
27
+ )
28
+ : []
29
+ })
30
+
31
+ // Cookies
32
+ const responseCookies = computed(() => {
33
+ const cookies = activeResponse.value?.cookies
34
+
35
+ return cookies
36
+ ? Object.keys(cookies).map((key) => ({ name: key, value: cookies[key] }))
37
+ : []
38
+ })
39
+
40
+ // Check if string is JSON
41
+ const isJsonString = (value?: string) => {
42
+ if (typeof value !== 'string') {
43
+ return false
44
+ }
45
+
46
+ try {
47
+ JSON.parse(value)
48
+ } catch {
49
+ return false
50
+ }
51
+
52
+ return true
53
+ }
54
+
55
+ // Pretty print JSON
56
+ const responseData = computed(() => {
57
+ const value = activeResponse.value?.data
58
+
59
+ if (value && isJsonString(value)) {
60
+ return JSON.stringify(JSON.parse(value), null, 2)
61
+ }
62
+
63
+ return value
64
+ })
65
+ </script>
66
+ <template>
67
+ <div class="scalar-api-client__main__right custom-scroll">
68
+ <div class="scalar-api-client__main__content">
69
+ <label>Response</label>
70
+ <div class="meta">
71
+ <template v-if="activeRequestId && activeResponse">
72
+ <ResponseMetaInformation :response="activeResponse" />
73
+ </template>
74
+ <template v-else>
75
+ <div class="meta-item">
76
+ <span>Send your first request to start</span>
77
+ </div>
78
+ </template>
79
+ </div>
80
+ </div>
81
+ <div>
82
+ <ResponseBody
83
+ :active="!!activeResponse"
84
+ :data="responseData" />
85
+ <!-- <CollapsibleSection title="Co Pilot">
86
+ <Copilot />
87
+ <template v-if="responseHeaders.length === 0">
88
+ <pre>No headers</pre>
89
+ </template>
90
+ </CollapsibleSection> -->
91
+ <ResponseHeaders :headers="responseHeaders" />
92
+ <CollapsibleSection title="Cookies">
93
+ <SimpleGrid
94
+ v-show="responseCookies.length > 0"
95
+ :items="responseCookies" />
96
+ <template v-if="responseCookies.length === 0">
97
+ <div class="scalar-api-client__empty-state">No Cookies</div>
98
+ </template>
99
+ </CollapsibleSection>
100
+ <div class="scalar-api-client__main__scroll-container" />
101
+ </div>
102
+ </div>
103
+ </template>
104
+ <style>
105
+ .scalar-api-client__main__right {
106
+ width: 50%;
107
+ padding: 0 0 12px 12px;
108
+ }
109
+ @media screen and (max-width: 820px) {
110
+ .scalar-api-client__main__right {
111
+ width: 100%;
112
+ border-right: none;
113
+ }
114
+ }
115
+ .scalar-api-client__main__right :deep(.scalar-copilot__header-button) {
116
+ position: absolute;
117
+ top: 6px;
118
+ right: 12px;
119
+ }
120
+ </style>
@@ -0,0 +1,23 @@
1
+ <script lang="ts" setup>
2
+ import { CodeMirror } from '../../CodeMirror'
3
+ import { CollapsibleSection } from '../../CollapsibleSection'
4
+
5
+ withDefaults(defineProps<{ active: boolean; data: any }>(), {
6
+ active: false,
7
+ data: null,
8
+ })
9
+ </script>
10
+ <template>
11
+ <CollapsibleSection title="Body">
12
+ <CodeMirror
13
+ v-if="active"
14
+ :content="data"
15
+ :languages="['json']"
16
+ :readOnly="true" />
17
+ <div
18
+ v-else
19
+ class="scalar-api-client__empty-state">
20
+ No Response
21
+ </div>
22
+ </CollapsibleSection>
23
+ </template>