@scalar/api-reference 0.5.0 → 0.5.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 (36) hide show
  1. package/dist/components/Content/Introduction/BaseUrl.vue.d.ts.map +1 -1
  2. package/dist/components/Content/MarkdownRenderer.vue.d.ts.map +1 -1
  3. package/dist/components/Content/ReferenceEndpoint/Copy.vue.d.ts.map +1 -1
  4. package/dist/components/Content/ReferenceEndpoint/ExampleRequest.vue.d.ts.map +1 -1
  5. package/dist/components/Content/ReferenceEndpoint/{ExampleResponses.vue.d.ts → ExampleResponses/ExampleResponses.vue.d.ts} +1 -1
  6. package/dist/components/Content/ReferenceEndpoint/ExampleResponses/ExampleResponses.vue.d.ts.map +1 -0
  7. package/dist/components/Content/ReferenceEndpoint/ExampleResponses/Headers.vue.d.ts +14 -0
  8. package/dist/components/Content/ReferenceEndpoint/ExampleResponses/Headers.vue.d.ts.map +1 -0
  9. package/dist/components/Content/ReferenceEndpoint/ExampleResponses/SelectExample.vue.d.ts +13 -0
  10. package/dist/components/Content/ReferenceEndpoint/ExampleResponses/SelectExample.vue.d.ts.map +1 -0
  11. package/dist/components/Content/ReferenceEndpoint/ExampleResponses/index.d.ts +2 -0
  12. package/dist/components/Content/ReferenceEndpoint/ExampleResponses/index.d.ts.map +1 -0
  13. package/dist/components/Sidebar.vue.d.ts.map +1 -1
  14. package/dist/helpers/index.d.ts +1 -0
  15. package/dist/helpers/index.d.ts.map +1 -1
  16. package/dist/helpers/mapFromObject.d.ts +8 -0
  17. package/dist/helpers/mapFromObject.d.ts.map +1 -0
  18. package/dist/index.js +8898 -11685
  19. package/dist/types.d.ts +9 -7
  20. package/dist/types.d.ts.map +1 -1
  21. package/package.json +5 -4
  22. package/src/components/Content/Introduction/BaseUrl.vue +22 -5
  23. package/src/components/Content/MarkdownRenderer.vue +5 -2
  24. package/src/components/Content/ReferenceEndpoint/Copy.vue +2 -1
  25. package/src/components/Content/ReferenceEndpoint/ExampleRequest.vue +17 -4
  26. package/src/components/Content/ReferenceEndpoint/{ExampleResponses.vue → ExampleResponses/ExampleResponses.vue} +56 -57
  27. package/src/components/Content/ReferenceEndpoint/ExampleResponses/Headers.vue +83 -0
  28. package/src/components/Content/ReferenceEndpoint/ExampleResponses/SelectExample.vue +129 -0
  29. package/src/components/Content/ReferenceEndpoint/ExampleResponses/index.ts +1 -0
  30. package/src/components/Content/ReferenceEndpoint/ReferenceEndpoint.vue +1 -1
  31. package/src/components/Sidebar.vue +6 -2
  32. package/src/components/SimpleTable/SimpleCell.vue +1 -0
  33. package/src/helpers/index.ts +1 -0
  34. package/src/helpers/mapFromObject.ts +11 -0
  35. package/src/types.ts +13 -10
  36. package/dist/components/Content/ReferenceEndpoint/ExampleResponses.vue.d.ts.map +0 -1
package/dist/types.d.ts CHANGED
@@ -42,15 +42,17 @@ export type Operation = {
42
42
  description: string;
43
43
  information: Information;
44
44
  };
45
+ export type ExampleResponseHeaders = Record<string, {
46
+ description: string;
47
+ schema: {
48
+ type: string;
49
+ format?: string;
50
+ example?: string;
51
+ };
52
+ }>;
45
53
  export type TransformedOperation = Operation & {
46
54
  responses: Record<string, Response & {
47
- headers: Record<string, {
48
- description: string;
49
- schema: {
50
- type: string;
51
- format?: string;
52
- };
53
- }>;
55
+ headers: ExampleResponseHeaders;
54
56
  }>;
55
57
  };
56
58
  export type Tag = {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "documentation",
12
12
  "component"
13
13
  ],
14
- "version": "0.5.0",
14
+ "version": "0.5.1",
15
15
  "author": "Scalar (https://github.com/scalar)",
16
16
  "homepage": "https://github.com/scalar/scalar",
17
17
  "repository": {
@@ -51,6 +51,7 @@
51
51
  "rehype-format": "4.0.1",
52
52
  "rehype-sanitize": "5.0.1",
53
53
  "rehype-stringify": "9.0.3",
54
+ "remark-breaks": "^3.0.3",
54
55
  "remark-gfm": "3.0.1",
55
56
  "remark-parse": "10.0.2",
56
57
  "remark-rehype": "10.1.0",
@@ -58,10 +59,10 @@
58
59
  "typographic-base": "1.0.4",
59
60
  "unified": "10.1.2",
60
61
  "xmldom": "0.6.0",
61
- "@scalar/api-client": "0.5.0",
62
+ "@scalar/api-client": "0.5.1",
62
63
  "@scalar/default-theme": "0.2.1",
63
- "@scalar/swagger-editor": "0.5.0",
64
- "@scalar/swagger-parser": "0.4.1",
64
+ "@scalar/swagger-editor": "0.5.1",
65
+ "@scalar/swagger-parser": "0.4.2",
65
66
  "@scalar/use-clipboard": "0.4.1",
66
67
  "@scalar/use-codemirror": "0.5.0",
67
68
  "@scalar/use-keyboard-event": "0.4.1",
@@ -1,7 +1,8 @@
1
1
  <script lang="ts" setup>
2
2
  import { useClipboard } from '@scalar/use-clipboard'
3
+ import { computed } from 'vue'
3
4
 
4
- defineProps<{
5
+ const props = defineProps<{
5
6
  server?: {
6
7
  url: string
7
8
  description?: string
@@ -9,23 +10,39 @@ defineProps<{
9
10
  }>()
10
11
 
11
12
  const { copyToClipboard } = useClipboard()
13
+
14
+ const formattedServerUrl = computed(() => {
15
+ const url = props.server?.url ?? ''
16
+ const urlWithoutHtml = url.replace(/(<([^>]+)>)/gi, '')
17
+
18
+ /* Replace all variables (example: {{ baseurl }} with an HTML tag) */
19
+ return urlWithoutHtml.replace(
20
+ /{{\s*([\w.-]+)\s*}}/g,
21
+ '<span class="base-url-variable">{{ $1 }}</span>',
22
+ )
23
+ })
12
24
  </script>
13
25
  <template>
14
26
  <template v-if="server">
15
27
  <a
16
28
  class="base-url"
17
29
  :title="server.description"
18
- @click="copyToClipboard(server.url)">
19
- {{ server.url }}
20
- </a>
30
+ @click="copyToClipboard(server.url)"
31
+ v-html="formattedServerUrl" />
21
32
  </template>
22
33
  </template>
34
+
35
+ <style>
36
+ .base-url-variable {
37
+ color: var(--theme-color-disabled);
38
+ }
39
+ </style>
40
+
23
41
  <style scoped>
24
42
  .base-url {
25
43
  color: var(--theme-color-2);
26
44
  font-size: var(--theme-mini);
27
45
  cursor: pointer;
28
- display: flex;
29
46
  font-family: var(--theme-font-code);
30
47
  flex-direction: column;
31
48
  }
@@ -3,6 +3,7 @@ import rehypeDocument from 'rehype-document'
3
3
  import rehypeFormat from 'rehype-format'
4
4
  import rehypeSanitize, { defaultSchema } from 'rehype-sanitize'
5
5
  import rehypeStringify from 'rehype-stringify'
6
+ import remarkBreaks from 'remark-breaks'
6
7
  import remarkGfm from 'remark-gfm'
7
8
  import remarkParse from 'remark-parse'
8
9
  import remarkRehype from 'remark-rehype'
@@ -20,6 +21,7 @@ watch(
20
21
  () => {
21
22
  unified()
22
23
  .use(remarkParse)
24
+ .use(remarkBreaks)
23
25
  .use(remarkGfm)
24
26
  .use(remarkRehype)
25
27
  .use(remarkTextr, { plugins: [typographicBase] })
@@ -59,6 +61,7 @@ watch(
59
61
  .markdown :deep(h6) {
60
62
  font-size: var(--font-size);
61
63
  margin: 12px 0 6px;
64
+ font-weight: var(--theme-bold);
62
65
  }
63
66
 
64
67
  .markdown :deep(p) {
@@ -123,7 +126,7 @@ watch(
123
126
  border-collapse: collapse;
124
127
  table-layout: fixed;
125
128
  width: 100%;
126
- margin: 0;
129
+ margin: 1em 0;
127
130
  overflow: hidden;
128
131
  box-shadow: 0 0 0 1px var(--theme-border-color);
129
132
  border-radius: var(--theme-radius-lg);
@@ -149,7 +152,7 @@ watch(
149
152
  margin-top: 4px;
150
153
  font-size: var(--theme-small);
151
154
  color: var(--theme-color-2);
152
- line-height: initial;
155
+ line-height: 1.4;
153
156
  }
154
157
  .markdown :deep(td:first-of-type),
155
158
  .markdown :deep(th:first-of-type) {
@@ -9,6 +9,7 @@ import { computed, onMounted, ref } from 'vue'
9
9
 
10
10
  import { useTemplateStore } from '../../../stores/template'
11
11
  import type { Tag } from '../../../types'
12
+ import MarkdownRenderer from '../MarkdownRenderer.vue'
12
13
  import Parameters from './Parameters.vue'
13
14
  import RequestBody from './RequestBody.vue'
14
15
 
@@ -72,7 +73,7 @@ onMounted(() => {
72
73
  </div>
73
74
  <div>
74
75
  <p class="tag-description">
75
- {{ operation.description }}
76
+ <MarkdownRenderer :value="operation.description" />
76
77
  </p>
77
78
  </div>
78
79
  <Parameters
@@ -55,26 +55,39 @@ async function generateSnippet() {
55
55
  if (pathVariables) {
56
56
  pathVariables.forEach((variable) => {
57
57
  const variableName = variable.replace(/{|}/g, '')
58
- path = path.replace(variable, variableName.toUpperCase())
58
+ path = path.replace(variable, `__${variableName.toUpperCase()}__`)
59
+ })
60
+ }
61
+
62
+ let url = props.server.url
63
+
64
+ // Replace all variables of the format {something} with the uppercase variable name without the brackets
65
+ const urlVariables = url.match(/{{(.*?)}}/g)
66
+
67
+ if (urlVariables) {
68
+ console.log(urlVariables)
69
+ urlVariables.forEach((variable) => {
70
+ const variableName = variable.replace(/{|}/g, '')
71
+ url = url.replace(variable, `__${variableName}__`)
59
72
  })
60
73
  }
61
74
 
62
75
  if (templateState.preferredLanguage === 'axios') {
63
76
  return generateAxiosCodeFromRequest({
64
77
  method: props.operation.httpVerb.toUpperCase(),
65
- url: `${props.server.url}${path}`,
78
+ url: `${url}${path}`,
66
79
  })
67
80
  } else if (templateState.preferredLanguage === 'laravel') {
68
81
  return generateLaravelCodeFromRequest({
69
82
  method: props.operation.httpVerb.toUpperCase(),
70
- url: `${props.server.url}${path}`,
83
+ url: `${url}${path}`,
71
84
  })
72
85
  }
73
86
 
74
87
  try {
75
88
  const snippet = new HTTPSnippet({
76
89
  method: props.operation.httpVerb.toUpperCase(),
77
- url: `${props.server.url}${path}`,
90
+ url: `${url}${path}`,
78
91
  } as HarRequest)
79
92
  const output = (await snippet.convert(
80
93
  templateState.preferredLanguage as TargetId,
@@ -1,24 +1,19 @@
1
1
  <script lang="ts" setup>
2
- import { type HttpHeader, httpHeaders } from '@scalar/api-client'
3
2
  import { useClipboard } from '@scalar/use-clipboard'
4
3
  import { CodeMirror } from '@scalar/use-codemirror'
5
4
  import { computed, ref } from 'vue'
6
5
 
7
- import type { TransformedOperation } from '../../../types'
6
+ import type { TransformedOperation } from '../../../../types'
8
7
  import {
9
8
  Card,
10
9
  CardContent,
11
10
  CardFooter,
12
11
  CardTab,
13
12
  CardTabHeader,
14
- } from '../../Card'
15
- import { Icon } from '../../Icon'
16
- import {
17
- SimpleCell,
18
- SimpleHeader,
19
- SimpleRow,
20
- SimpleTable,
21
- } from '../../SimpleTable'
13
+ } from '../../../Card'
14
+ import { Icon } from '../../../Icon'
15
+ import Headers from './Headers.vue'
16
+ import SelectExample from './SelectExample.vue'
22
17
 
23
18
  const props = defineProps<{ operation: TransformedOperation }>()
24
19
 
@@ -46,29 +41,24 @@ const currentResponse = computed(() => {
46
41
  return props.operation.responses?.[currentStatusCode]
47
42
  })
48
43
 
49
- const currentResponseJsonBody = computed(() => {
50
- return currentResponse.value?.content?.['application/json']?.body
44
+ const currentResponseExamples = computed(() => {
45
+ const examples =
46
+ currentResponse.value?.content?.['application/json']?.examples
47
+
48
+ if (examples) {
49
+ return JSON.parse(examples)
50
+ }
51
+
52
+ return false
53
+ })
54
+
55
+ const currentResponseExample = computed(() => {
56
+ return currentResponse.value?.content?.['application/json']?.example
51
57
  })
52
58
 
53
59
  const changeTab = (index: number) => {
54
60
  selectedResponseIndex.value = index
55
61
  }
56
-
57
- const getDocumentationUrlForHttpHeader = (headerName: string) => {
58
- return httpHeaders.find((header: HttpHeader) => {
59
- return header.name.toLowerCase() === headerName.toLowerCase()
60
- })?.url
61
- }
62
-
63
- // Make the first letter and all letters after a - uppercase
64
- const formatHeaderName = (headerName: string) => {
65
- return headerName
66
- .split('-')
67
- .map((word) => {
68
- return word.charAt(0).toUpperCase() + word.slice(1)
69
- })
70
- .join('-')
71
- }
72
62
  </script>
73
63
  <template>
74
64
  <Card v-if="orderedStatusCodes.length">
@@ -83,10 +73,10 @@ const formatHeaderName = (headerName: string) => {
83
73
 
84
74
  <template #actions>
85
75
  <button
86
- v-if="currentResponseJsonBody"
76
+ v-if="currentResponseExample"
87
77
  class="code-copy"
88
78
  type="button"
89
- @click="() => copyToClipboard(currentResponseJsonBody)">
79
+ @click="() => copyToClipboard(currentResponseExample)">
90
80
  <Icon
91
81
  src="solid/interface-copy-clipboard"
92
82
  width="10px" />
@@ -96,35 +86,24 @@ const formatHeaderName = (headerName: string) => {
96
86
  <CardContent
97
87
  v-if="currentResponse.headers"
98
88
  muted>
99
- <SimpleTable>
100
- <SimpleRow>
101
- <SimpleHeader>Header</SimpleHeader>
102
- <SimpleHeader>Description</SimpleHeader>
103
- </SimpleRow>
104
- <SimpleRow
105
- v-for="(data, header) in currentResponse.headers"
106
- :key="header">
107
- <SimpleCell
108
- :href="getDocumentationUrlForHttpHeader(header)"
109
- :strong="true"
110
- :wrap="false">
111
- {{ formatHeaderName(header) }}
112
- </SimpleCell>
113
- <SimpleCell>{{ data.description }}</SimpleCell>
114
- </SimpleRow>
115
- </SimpleTable>
89
+ <Headers :headers="currentResponse.headers" />
116
90
  </CardContent>
117
91
  <CardContent muted>
118
- <CodeMirror
119
- v-show="currentResponseJsonBody"
120
- :content="currentResponseJsonBody"
121
- :languages="['json']"
122
- readOnly />
123
- <div
124
- v-if="!currentResponseJsonBody"
125
- class="scalar-api-reference__empty-state">
126
- No Body
127
- </div>
92
+ <template v-if="currentResponseExamples">
93
+ <SelectExample :examples="currentResponseExamples" />
94
+ </template>
95
+ <template v-else>
96
+ <CodeMirror
97
+ v-show="currentResponseExample"
98
+ :content="currentResponseExample"
99
+ :languages="['json']"
100
+ readOnly />
101
+ <div
102
+ v-if="!currentResponseExample"
103
+ class="scalar-api-reference__empty-state">
104
+ No Body
105
+ </div>
106
+ </template>
128
107
  </CardContent>
129
108
  <CardFooter
130
109
  v-if="currentResponse?.description"
@@ -166,4 +145,24 @@ const formatHeaderName = (headerName: string) => {
166
145
  padding: 20px;
167
146
  color: var(--theme-color-2);
168
147
  }
148
+
149
+ .schema-type {
150
+ font-size: var(--theme-micro);
151
+ color: var(--theme-color-2);
152
+ font-weight: var(--theme-semibold);
153
+ background: var(--theme-background-3);
154
+ padding: 2px 4px;
155
+ border-radius: 4px;
156
+ margin-right: 4px;
157
+ }
158
+ .schema-example {
159
+ font-size: var(--theme-micro);
160
+ color: var(--theme-color-2);
161
+ font-weight: var(--theme-semibold);
162
+ }
163
+
164
+ .example-response-tab {
165
+ display: block;
166
+ margin: 6px;
167
+ }
169
168
  </style>
@@ -0,0 +1,83 @@
1
+ <script lang="ts" setup>
2
+ import { type HttpHeader, httpHeaders } from '@scalar/api-client'
3
+ import { computed } from 'vue'
4
+
5
+ import { mapFromObject } from '../../../../helpers'
6
+ import type { ExampleResponseHeaders } from '../../../../types'
7
+ import {
8
+ SimpleCell,
9
+ SimpleHeader,
10
+ SimpleRow,
11
+ SimpleTable,
12
+ } from '../../../SimpleTable'
13
+
14
+ const props = defineProps<{
15
+ headers: ExampleResponseHeaders
16
+ }>()
17
+
18
+ const getDocumentationUrlForHttpHeader = (headerName: string) => {
19
+ return httpHeaders.find((header: HttpHeader) => {
20
+ return header.name.toLowerCase() === headerName.toLowerCase()
21
+ })?.url
22
+ }
23
+
24
+ // Make the first letter and all letters after a - uppercase
25
+ const formatHeaderName = (headerName: string) => {
26
+ return headerName
27
+ .split('-')
28
+ .map((word) => {
29
+ return word.charAt(0).toUpperCase() + word.slice(1)
30
+ })
31
+ .join('-')
32
+ }
33
+
34
+ const headersHaveDescription = computed(() => {
35
+ const headers = mapFromObject(props.headers)
36
+
37
+ return headers.some((header: any) => {
38
+ return header.value.description
39
+ })
40
+ })
41
+
42
+ const headersHaveSchema = computed(() => {
43
+ const headers = mapFromObject(props.headers)
44
+
45
+ return headers.some((header: any) => {
46
+ return header.value.schema
47
+ })
48
+ })
49
+ </script>
50
+
51
+ <template>
52
+ <SimpleTable>
53
+ <SimpleRow>
54
+ <SimpleHeader>Header</SimpleHeader>
55
+ <SimpleHeader v-if="headersHaveDescription">Description</SimpleHeader>
56
+ <SimpleHeader v-if="headersHaveSchema">Value</SimpleHeader>
57
+ </SimpleRow>
58
+ <SimpleRow
59
+ v-for="(data, header) in headers"
60
+ :key="header">
61
+ <SimpleCell
62
+ :href="getDocumentationUrlForHttpHeader(header)"
63
+ :strong="true"
64
+ :wrap="false">
65
+ {{ formatHeaderName(header) }}
66
+ </SimpleCell>
67
+ <SimpleCell v-if="headersHaveDescription">{{ data }}</SimpleCell>
68
+ <SimpleCell v-if="headersHaveSchema">
69
+ <span v-if="data.schema.example">
70
+ <code class="schema-example">{{ data.schema.example }}</code>
71
+ </span>
72
+ <code
73
+ v-else-if="data.schema.type"
74
+ class="schema-type">
75
+ {{ data.schema.type }}
76
+ </code>
77
+ <code v-else>
78
+ {{ data.schema }}
79
+ </code>
80
+ </SimpleCell>
81
+ </SimpleRow>
82
+ </SimpleTable>
83
+ </template>
@@ -0,0 +1,129 @@
1
+ <script lang="ts" setup>
2
+ import {
3
+ Listbox,
4
+ ListboxButton,
5
+ ListboxOption,
6
+ ListboxOptions,
7
+ } from '@headlessui/vue'
8
+ import { CodeMirror } from '@scalar/use-codemirror'
9
+ import { ref } from 'vue'
10
+
11
+ import { mapFromObject } from '../../../../helpers'
12
+ import { Icon } from '../../../Icon'
13
+
14
+ const props = defineProps<{ examples: Record<string, any> }>()
15
+
16
+ const examples = mapFromObject(props.examples)
17
+ const selectedExample = ref(examples[0])
18
+ </script>
19
+ <template>
20
+ <div class="example-switcher">
21
+ <label
22
+ class="listbox-label"
23
+ for="listbox-button">
24
+ Select Example
25
+ </label>
26
+ <Listbox v-model="selectedExample">
27
+ <ListboxButton
28
+ id="listbox-button"
29
+ class="listbox-button">
30
+ <div class="listbox-button-content">
31
+ <div class="listbox-button-label">
32
+ {{ selectedExample.value.summary ?? selectedExample.key }}
33
+ </div>
34
+ <div>
35
+ <Icon
36
+ class="icon"
37
+ src="line/arrow-chevron-down" />
38
+ </div>
39
+ </div>
40
+ </ListboxButton>
41
+
42
+ <ListboxOptions class="listbox-options">
43
+ <ListboxOption
44
+ v-for="example in examples"
45
+ :key="example.key"
46
+ class="listbox-option"
47
+ :value="example">
48
+ {{ example.value.summary ?? example.key }}
49
+ </ListboxOption>
50
+ </ListboxOptions>
51
+ </Listbox>
52
+ <CodeMirror
53
+ :content="JSON.stringify(selectedExample.value.value, null, 2)"
54
+ :languages="['json']"
55
+ readOnly />
56
+ </div>
57
+ </template>
58
+
59
+ <style scoped>
60
+ .example-switcher {
61
+ display: flex;
62
+ gap: 6px;
63
+ flex-direction: column;
64
+ }
65
+
66
+ .listbox-label {
67
+ font-size: var(--theme-mini);
68
+ font-weight: var(--theme-semibold);
69
+ margin: 0 4px;
70
+ color: var(--theme-color-2);
71
+ }
72
+
73
+ .listbox-button {
74
+ border: 1px solid var(--theme-border-color);
75
+ background: var(--theme-background-1);
76
+ padding: 6px 12px;
77
+ border-radius: var(--theme-radius);
78
+ text-align: left;
79
+ display: block;
80
+ font-size: var(--theme-mini);
81
+ }
82
+
83
+ .listbox-button-content {
84
+ display: flex;
85
+ align-items: center;
86
+ justify-content: space-between;
87
+ }
88
+
89
+ .listbox-button-label {
90
+ white-space: nowrap;
91
+ overflow: hidden;
92
+ text-overflow: ellipsis;
93
+ }
94
+
95
+ .listbox-options {
96
+ background: var(--theme-background-1);
97
+ padding: 6px 6px;
98
+ border-radius: var(--theme-radius-lg);
99
+ margin-top: 4px;
100
+ box-shadow: var(--theme-shadow-2);
101
+ position: absolute;
102
+ margin: 0 1px;
103
+ transform: translateY(-50%);
104
+ z-index: 100;
105
+ }
106
+
107
+ .listbox-option {
108
+ padding: 6px 12px;
109
+ cursor: pointer;
110
+ color: var(--theme-color-1);
111
+ border-radius: var(--theme-radius);
112
+ margin: 2px 0;
113
+ }
114
+
115
+ .listbox-option[data-headlessui-state='selected'] {
116
+ background: var(--theme-background-2);
117
+ }
118
+
119
+ .listbox-option:hover {
120
+ background: var(--theme-background-2);
121
+ color: var(--theme-color-2);
122
+ }
123
+
124
+ .icon {
125
+ width: 13px;
126
+ height: 13px;
127
+ color: var(--theme-color-3);
128
+ }
129
+ </style>
@@ -0,0 +1 @@
1
+ export { default as ExampleResponses } from './ExampleResponses.vue'
@@ -2,7 +2,7 @@
2
2
  import type { Server, Tag, TransformedOperation } from '../../../types'
3
3
  import Copy from './Copy.vue'
4
4
  import ExampleRequest from './ExampleRequest.vue'
5
- import ExampleResponses from './ExampleResponses.vue'
5
+ import { ExampleResponses } from './ExampleResponses'
6
6
 
7
7
  defineProps<{
8
8
  operation: TransformedOperation
@@ -1,6 +1,10 @@
1
1
  <script setup lang="ts">
2
- import { generateRequest, useApiClientRequestStore } from '@scalar/api-client'
3
- import { useApiClientStore, useOperation } from '@scalar/api-client'
2
+ import {
3
+ generateRequest,
4
+ useApiClientRequestStore,
5
+ useApiClientStore,
6
+ useOperation,
7
+ } from '@scalar/api-client'
4
8
  import { useKeyboardEvent } from '@scalar/use-keyboard-event'
5
9
  import { useMediaQuery } from '@vueuse/core'
6
10
 
@@ -30,6 +30,7 @@ withDefaults(
30
30
  padding: 0.25em 0.5em;
31
31
  color: var(--theme-color-1);
32
32
  white-space: nowrap;
33
+ vertical-align: top;
33
34
  }
34
35
 
35
36
  .simple-cell:last-of-type {
@@ -1,4 +1,5 @@
1
1
  export { generateAxiosCodeFromRequest } from './generateAxiosCodeFromRequest'
2
2
  export { generateLaravelCodeFromRequest } from './generateLaravelCodeFromRequest'
3
+ export { mapFromObject } from './mapFromObject'
3
4
  export { objectMerge } from './objectMerge'
4
5
  export { transformToJson } from './transformToJson'
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Map an object to an array of key-value pairs.
3
+ */
4
+ export const mapFromObject = (object: Record<string, any>) => {
5
+ return Object.keys(object).map((key) => {
6
+ return {
7
+ key,
8
+ value: object[key],
9
+ }
10
+ })
11
+ }