@scalar/api-client 3.21.0 → 3.21.2
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.
- package/CHANGELOG.md +59 -0
- package/dist/components/SectionFilter.vue.d.ts +0 -2
- package/dist/components/SectionFilter.vue.d.ts.map +1 -1
- package/dist/components/SectionFilter.vue.js +1 -1
- package/dist/components/SectionFilter.vue.js.map +1 -1
- package/dist/components/SectionFilter.vue.script.js +2 -8
- package/dist/components/SectionFilter.vue.script.js.map +1 -1
- package/dist/components/SectionFilterButton.vue.d.ts +0 -1
- package/dist/components/SectionFilterButton.vue.d.ts.map +1 -1
- package/dist/components/SectionFilterButton.vue.js.map +1 -1
- package/dist/components/SectionFilterButton.vue.script.js +2 -10
- package/dist/components/SectionFilterButton.vue.script.js.map +1 -1
- package/dist/style.css +156 -85
- package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/OperationBlock.vue.js.map +1 -1
- package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js +4 -0
- package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js.map +1 -1
- package/dist/v2/blocks/operation-block/components/Header.vue.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/components/Header.vue.js +1 -1
- package/dist/v2/blocks/operation-block/components/Header.vue.js.map +1 -1
- package/dist/v2/blocks/operation-block/components/Header.vue.script.js +2 -0
- package/dist/v2/blocks/operation-block/components/Header.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/RequestBlock.vue.d.ts +2 -0
- package/dist/v2/blocks/request-block/RequestBlock.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/RequestBlock.vue.js +1 -1
- package/dist/v2/blocks/request-block/RequestBlock.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/RequestBlock.vue.script.js +24 -6
- package/dist/v2/blocks/request-block/RequestBlock.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.d.ts +4 -0
- package/dist/v2/blocks/request-block/components/RequestBody.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.js +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js +8 -5
- package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBodyForm.vue.d.ts +2 -0
- package/dist/v2/blocks/request-block/components/RequestBodyForm.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBodyForm.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBodyForm.vue.script.js +12 -4
- package/dist/v2/blocks/request-block/components/RequestBodyForm.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js +5 -0
- package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTable.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTable.vue.js +1 -1
- package/dist/v2/blocks/request-block/components/RequestTable.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTable.vue.script.js +1 -0
- package/dist/v2/blocks/request-block/components/RequestTable.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTableRow.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js +2 -2
- package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/helpers/get-form-body-rows.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/helpers/get-form-body-rows.js +5 -3
- package/dist/v2/blocks/request-block/helpers/get-form-body-rows.js.map +1 -1
- package/dist/v2/blocks/response-block/ResponseBlock.vue.d.ts.map +1 -1
- package/dist/v2/blocks/response-block/ResponseBlock.vue.js +1 -1
- package/dist/v2/blocks/response-block/ResponseBlock.vue.js.map +1 -1
- package/dist/v2/blocks/response-block/ResponseBlock.vue.script.js +4 -3
- package/dist/v2/blocks/response-block/ResponseBlock.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.js +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.script.js +23 -43
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.d.ts +7 -0
- package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.script.js +6 -0
- package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.script.js +5 -5
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.script.js +11 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.js +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.js.map +1 -1
- package/dist/v2/components/code-input/CodeInputLite.vue.d.ts.map +1 -1
- package/dist/v2/components/code-input/CodeInputLite.vue.js +1 -1
- package/dist/v2/components/code-input/CodeInputLite.vue.js.map +1 -1
- package/dist/v2/components/code-input/CodeInputLite.vue.script.js +13 -1
- package/dist/v2/components/code-input/CodeInputLite.vue.script.js.map +1 -1
- package/dist/v2/components/data-table/DataTableInput.vue.d.ts.map +1 -1
- package/dist/v2/components/data-table/DataTableInput.vue.js +1 -1
- package/dist/v2/components/data-table/DataTableInput.vue.js.map +1 -1
- package/dist/v2/components/data-table/DataTableInput.vue.script.js +7 -2
- package/dist/v2/components/data-table/DataTableInput.vue.script.js.map +1 -1
- package/dist/v2/components/layout/CollapsibleSection.vue.d.ts +20 -0
- package/dist/v2/components/layout/CollapsibleSection.vue.d.ts.map +1 -1
- package/dist/v2/components/layout/CollapsibleSection.vue.js.map +1 -1
- package/dist/v2/components/layout/CollapsibleSection.vue.script.js +36 -16
- package/dist/v2/components/layout/CollapsibleSection.vue.script.js.map +1 -1
- package/dist/v2/components/layout/collapsible-section-heading-level.d.ts +13 -0
- package/dist/v2/components/layout/collapsible-section-heading-level.d.ts.map +1 -0
- package/dist/v2/components/layout/collapsible-section-heading-level.js +14 -0
- package/dist/v2/components/layout/collapsible-section-heading-level.js.map +1 -0
- package/dist/v2/components/layout/index.d.ts +1 -0
- package/dist/v2/components/layout/index.d.ts.map +1 -1
- package/dist/v2/components/layout/index.js +2 -1
- package/dist/v2/components/modals/ModalClientContainer.vue.d.ts.map +1 -1
- package/dist/v2/components/modals/ModalClientContainer.vue.js +1 -1
- package/dist/v2/components/modals/ModalClientContainer.vue.js.map +1 -1
- package/dist/v2/components/modals/ModalClientContainer.vue.script.js +10 -1
- package/dist/v2/components/modals/ModalClientContainer.vue.script.js.map +1 -1
- package/dist/v2/components/sidebar/SidebarToggle.vue.d.ts +15 -2
- package/dist/v2/components/sidebar/SidebarToggle.vue.d.ts.map +1 -1
- package/dist/v2/components/sidebar/SidebarToggle.vue.js +3 -1
- package/dist/v2/components/sidebar/SidebarToggle.vue.js.map +1 -1
- package/dist/v2/components/sidebar/SidebarToggle.vue.script.js +5 -5
- package/dist/v2/components/sidebar/SidebarToggle.vue.script.js.map +1 -1
- package/dist/v2/constants.js +1 -1
- package/dist/v2/features/modal/Modal.vue.d.ts.map +1 -1
- package/dist/v2/features/modal/Modal.vue.js.map +1 -1
- package/dist/v2/features/modal/Modal.vue.script.js +2 -1
- package/dist/v2/features/modal/Modal.vue.script.js.map +1 -1
- package/dist/vue-styles.css +118 -77
- package/package.json +12 -12
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,64 @@
|
|
|
1
1
|
# @scalar/api-client
|
|
2
2
|
|
|
3
|
+
## 3.21.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#10369](https://github.com/scalar/scalar/pull/10369): fix: correct the semantics of the authentication card and of nested schema lists
|
|
8
|
+
|
|
9
|
+
Two findings from an accessibility audit, both programmatic only with no change
|
|
10
|
+
to how anything renders:
|
|
11
|
+
- The reference's Authentication card announced its title as a level two
|
|
12
|
+
heading, which put a card of controls in the document outline next to the
|
|
13
|
+
real tag and operation headings. The title is now plain text and the card is
|
|
14
|
+
exposed as a named group instead, so it stays findable without claiming to
|
|
15
|
+
open a passage of the page. Collapsible sections in the API client are
|
|
16
|
+
unaffected and keep their headings.
|
|
17
|
+
- A schema panel whose root is a composition, a primitive or an array wraps a
|
|
18
|
+
single nameless row that carries the real property list, so assistive tech
|
|
19
|
+
announced "list with 1 item" before the list the reader wanted. That wrapper
|
|
20
|
+
is now presentational and only the real property list is announced.
|
|
21
|
+
|
|
22
|
+
- [#10371](https://github.com/scalar/scalar/pull/10371): fix: tidy the client modal header at narrow widths
|
|
23
|
+
|
|
24
|
+
The method label and copy button now stay inside the address bar at every width instead of moving to a floating row of their own, and the send button spans the full width once it wraps. Below the `lg` breakpoint, where the address bar fills the header row and its method chip reaches the panel edge, the sidebar toggle moves onto the backdrop as a circle that mirrors the close button in the opposite corner. At wider widths it keeps its original place inside the panel.
|
|
25
|
+
|
|
26
|
+
- [#10374](https://github.com/scalar/scalar/pull/10374): fix: resolve accessibility audit findings in the client modal
|
|
27
|
+
- Auth fields (Bearer Token, Username, API key and OAuth inputs) now expose their visible label as the accessible name in both the masked and unmasked state
|
|
28
|
+
- Request and response filter tabs no longer carry `aria-controls`, so screen readers announce each tab once when arrowing through them
|
|
29
|
+
- Opening the modal from a "Test Request" button now moves focus to the close button first
|
|
30
|
+
|
|
31
|
+
- [#10369](https://github.com/scalar/scalar/pull/10369): fix: address a batch of screen reader and keyboard accessibility findings
|
|
32
|
+
|
|
33
|
+
Corrects programmatic semantics only, with no change to how anything renders:
|
|
34
|
+
the current sidebar item now reports `aria-current`, the single content type
|
|
35
|
+
readout leaves the tab order, collapsible sections no longer announce their
|
|
36
|
+
title twice, the password toggle reports its state through `aria-pressed`, the
|
|
37
|
+
two document download buttons get distinct accessible names, response status
|
|
38
|
+
tabs announce what each code means, and the client picker and its search field
|
|
39
|
+
get accessible names.
|
|
40
|
+
|
|
41
|
+
- [#10361](https://github.com/scalar/scalar/pull/10361): Preserve configured OAuth redirect URLs when changing credentials or clearing tokens, and hide refresh controls when no refresh token is available.
|
|
42
|
+
|
|
43
|
+
Previously saved redirect overrides, including empty strings and prefilled page origins, remain unchanged because they cannot be distinguished from intentional user choices. Users affected by the earlier bug must enter the intended redirect URL again.
|
|
44
|
+
|
|
45
|
+
The public `@scalar/workspace-store` OAuth secrets types now expose `x-scalar-secret-redirect-uri` as optional (`string | undefined`). Consumers must handle an absent override separately from an explicit empty string.
|
|
46
|
+
|
|
47
|
+
- [#10363](https://github.com/scalar/scalar/pull/10363): Avoid duplicate available OAuth2 entries when scopes are selected, and apply configured default scopes when selecting an available scheme.
|
|
48
|
+
|
|
49
|
+
## 3.21.1
|
|
50
|
+
|
|
51
|
+
### Patch Changes
|
|
52
|
+
|
|
53
|
+
- [#10350](https://github.com/scalar/scalar/pull/10350): Keep long response bodies scrollable inside the body panel in narrow API client layouts.
|
|
54
|
+
- [#10192](https://github.com/scalar/scalar/pull/10192): Mock-server XML response bytes now use the shared schema-aware serializer instead of `json2xml`, including attributes, namespaces, and root naming. Existing XML response snapshots may need updating. Supplied serialized XML remains unchanged.
|
|
55
|
+
|
|
56
|
+
Generate XML examples from schema metadata, preserving attributes, namespaces, array wrappers, repeated elements, and OpenAPI 3.2 text and CDATA nodes. Use the same XML serialization for request bodies, code snippets, response examples, mock responses, and Markdown documentation. Preserve serialized media examples and escape schema string examples as element text.
|
|
57
|
+
|
|
58
|
+
Explain XML generation failures in response example panels, including the serialized-example escape hatch for large payloads. Expose XML generation failures in mock response headers with `X-Scalar-XML-Error`, containing the first error diagnostic code. Report diagnostics to other consumers through a callback or the developer console, and format element-only descendants within mixed content without changing text values.
|
|
59
|
+
|
|
60
|
+
- [#10334](https://github.com/scalar/scalar/pull/10334): Include optional form fields when selecting files or editing values, while preserving explicitly unchecked fields.
|
|
61
|
+
|
|
3
62
|
## 3.21.0
|
|
4
63
|
|
|
5
64
|
### Minor Changes
|
|
@@ -3,8 +3,6 @@ declare const __VLS_export: <T extends string>(__VLS_props: NonNullable<Awaited<
|
|
|
3
3
|
filters?: T[];
|
|
4
4
|
/** Localized labels keyed by stable filter IDs. */
|
|
5
5
|
labels?: Partial<Record<T, string>>;
|
|
6
|
-
/** IDs for the currently available sections. */
|
|
7
|
-
filterIds?: Partial<Record<T, string>>;
|
|
8
6
|
} & {
|
|
9
7
|
modelValue?: T;
|
|
10
8
|
}) & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SectionFilter.vue.d.ts","sourceRoot":"","sources":["../../src/components/SectionFilter.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SectionFilter.vue.d.ts","sourceRoot":"","sources":["../../src/components/SectionFilter.vue"],"names":[],"mappings":"AAqLA,QAAA,MAAM,YAAY,GAAK,CAAC,SAAS,MAAM,EACtC,aAAa,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,EAC9D,YAAY,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC,EAC3G,gBAAgB,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAClE;WAsNO,OAAO,KAAK,EAAE,WAAW,GAAG,mBAAmB,CAAC;kBApN5C,CAAC,EAAE;QACb,mDAAmD;iBAC1C,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;;qBAqCxB,CAAC;;;KA6K6E,CAAC,GAAG,CAAC,OAAO,UAAU,SAAS;QAAE,oBAAoB,EAAE,MAAM,CAAC,CAAA;KAAE,GAAG,CAAC,GAAG,EAAE,CAAC;YAC5J,CAAC,OAAO,EAAE,EAAE,KAAK,IAAI;WACtB,GAAG;WACH,EAAE;;EAGN,KACQ,OAAO,KAAK,EAAE,KAAK,GAAG;IAAE,KAAK,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,WAAW,CAAC,CAAC,CAAA;CAAI,CAAC;wBACpE,OAAO,YAAY;AAAxC,wBAAyC;AACzC,KAAK,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,GAAG,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,GAAG;KAAG,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAAG,CAAC,GAAG,EAAE,CAAC"}
|
|
@@ -2,7 +2,7 @@ import _plugin_vue_export_helper_default from "../_virtual/_plugin-vue_export-he
|
|
|
2
2
|
import SectionFilter_vue_vue_type_script_setup_true_lang_default from "./SectionFilter.vue.script.js";
|
|
3
3
|
/* empty css */
|
|
4
4
|
//#region src/components/SectionFilter.vue
|
|
5
|
-
var SectionFilter_default = /*#__PURE__*/ _plugin_vue_export_helper_default(SectionFilter_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-
|
|
5
|
+
var SectionFilter_default = /*#__PURE__*/ _plugin_vue_export_helper_default(SectionFilter_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-50fd0a3c"]]);
|
|
6
6
|
//#endregion
|
|
7
7
|
export { SectionFilter_default as default };
|
|
8
8
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SectionFilter.vue.js","names":[],"sources":["../../src/components/SectionFilter.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"T extends string\">\nimport { ScalarIcon } from '@scalar/components/icon'\nimport { nextTick, ref } from 'vue'\n\nimport SectionFilterButton from '@/components/SectionFilterButton.vue'\nimport { useLocalization } from '@/v2/features/localization'\n\nconst {
|
|
1
|
+
{"version":3,"file":"SectionFilter.vue.js","names":[],"sources":["../../src/components/SectionFilter.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"T extends string\">\nimport { ScalarIcon } from '@scalar/components/icon'\nimport { nextTick, ref } from 'vue'\n\nimport SectionFilterButton from '@/components/SectionFilterButton.vue'\nimport { useLocalization } from '@/v2/features/localization'\n\nconst { filters = [], labels } = defineProps<{\n filters?: T[]\n /** Localized labels keyed by stable filter IDs. */\n labels?: Partial<Record<T, string>>\n}>()\n\nconst model = defineModel<T>()\n\nconst tablist = ref<HTMLDivElement>()\nconst { direction } = useLocalization()\n\n/** Keyboard navigation */\nconst navigateSection = (arrow: 'left' | 'right'): void => {\n // Flex rows reverse in RTL, so the visual arrow direction reverses the index step.\n const offset =\n (arrow === 'left' ? -1 : 1) * (direction.value === 'rtl' ? -1 : 1)\n const index = model.value ? filters.indexOf(model.value) : 0\n const length = filters.length\n\n // Ensures we loop around the array by using the remainder\n const newIndex = (index + offset + length) % length\n model.value = filters[newIndex]\n\n // Focus the selected button\n nextTick(() => {\n if (tablist.value) {\n const selectedButton = tablist.value.querySelector(\n `button[aria-selected=\"true\"]`,\n ) satisfies HTMLButtonElement | null\n if (selectedButton) {\n selectedButton.focus()\n }\n }\n })\n}\n</script>\n<template>\n <div\n ref=\"tablist\"\n class=\"filter-hover context-bar-group ms-auto hidden lg:flex\"\n role=\"tablist\"\n @keydown.left=\"navigateSection('left')\"\n @keydown.right=\"navigateSection('right')\">\n <div\n class=\"request-section-content request-section-content-filter fade-request-section-content text-c-3 pointer-events-auto relative hidden w-full justify-end gap-[1.5px] rounded py-1.75 text-xs xl:flex\">\n <SectionFilterButton\n v-for=\"filter in filters\"\n :key=\"filter\"\n class=\"filter-hover-item\"\n role=\"tab\"\n :selected=\"model === filter\"\n @click=\"model = filter\">\n {{ labels?.[filter] ?? filter }}\n </SectionFilterButton>\n <div\n class=\"filter-button context-bar-group-hover:text-c-1 absolute -end-[30px] flex items-center\">\n <span class=\"context-bar-group-hover:hidden me-1.5\">{{\n model ? (labels?.[model] ?? model) : model\n }}</span>\n <ScalarIcon\n icon=\"FilterList\"\n size=\"md\"\n thickness=\"2\" />\n </div>\n </div>\n </div>\n</template>\n<style scoped>\n.fade-request-section-content {\n background: linear-gradient(\n to left,\n var(--scalar-background-1) 64%,\n transparent\n );\n}\n.fade-request-section-content:dir(rtl) {\n background: linear-gradient(\n to right,\n var(--scalar-background-1) 64%,\n transparent\n );\n}\n.filter-hover {\n height: 100%;\n padding-inline-end: 39px;\n padding-inline-start: 24px;\n position: absolute;\n inset-inline-end: 0;\n transition: width 0s ease-in-out 0.2s;\n overflow: hidden;\n}\n.filter-hover:hover,\n.filter-hover:has(:focus-visible) {\n width: 100%;\n z-index: 10;\n}\n.filter-hover:before {\n content: '';\n position: absolute;\n top: 0;\n inset-inline-start: 0;\n width: 100%;\n height: fit-content;\n background-color: var(--scalar-background-1);\n opacity: 0;\n transition: all 0.3s ease-in-out;\n pointer-events: none;\n}\n.filter-hover-item {\n opacity: 0;\n}\n.filter-hover-item:not(:last-of-type) {\n transform: translate3d(0, 3px, 0);\n}\n.filter-hover:hover .filter-hover-item {\n transition:\n opacity 0.2s ease-in-out,\n transform 0.2s ease-in-out;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(1) {\n transition-delay: 0.05s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(2) {\n transition-delay: 0.1s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(3) {\n transition-delay: 0.15s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(4) {\n transition-delay: 0.2s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(5) {\n transition-delay: 0.25s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(6) {\n transition-delay: 0.3s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(7) {\n transition-delay: 0.35s;\n}\n.filter-hover:hover .filter-hover-item,\n.filter-hover:has(:focus-visible) .filter-hover-item {\n opacity: 1;\n transform: translate3d(0, 0, 0);\n}\n.filter-hover:hover:before,\n.filter-hover:has(:focus-visible):before {\n opacity: 0.9;\n backdrop-filter: blur(10px);\n}\n.filter-button {\n top: 50%;\n transform: translateY(-50%);\n}\n.context-bar-group:hover .context-bar-group-hover\\:text-c-1,\n.context-bar-group:has(:focus-visible) .context-bar-group-hover\\:text-c-1 {\n --tw-text-opacity: 1;\n color: rgb(var(--scalar-color-1) / var(--tw-text-opacity));\n}\n\n.context-bar-group:hover .context-bar-group-hover\\:hidden,\n.context-bar-group:has(:focus-visible) .context-bar-group-hover\\:hidden {\n display: none;\n}\n</style>\n"],"mappings":""}
|
|
@@ -10,8 +10,7 @@ var SectionFilter_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
|
|
|
10
10
|
__name: "SectionFilter",
|
|
11
11
|
props: /*@__PURE__*/ mergeModels({
|
|
12
12
|
filters: { default: () => [] },
|
|
13
|
-
labels: {}
|
|
14
|
-
filterIds: {}
|
|
13
|
+
labels: {}
|
|
15
14
|
}, {
|
|
16
15
|
"modelValue": {},
|
|
17
16
|
"modelModifiers": {}
|
|
@@ -46,18 +45,13 @@ var SectionFilter_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ de
|
|
|
46
45
|
return openBlock(), createBlock(SectionFilterButton_default, {
|
|
47
46
|
key: filter,
|
|
48
47
|
class: "filter-hover-item",
|
|
49
|
-
controls: __props.filterIds?.[filter],
|
|
50
48
|
role: "tab",
|
|
51
49
|
selected: model.value === filter,
|
|
52
50
|
onClick: ($event) => model.value = filter
|
|
53
51
|
}, {
|
|
54
52
|
default: withCtx(() => [createTextVNode(toDisplayString(__props.labels?.[filter] ?? filter), 1)]),
|
|
55
53
|
_: 2
|
|
56
|
-
}, 1032, [
|
|
57
|
-
"controls",
|
|
58
|
-
"selected",
|
|
59
|
-
"onClick"
|
|
60
|
-
]);
|
|
54
|
+
}, 1032, ["selected", "onClick"]);
|
|
61
55
|
}), 128)), createElementVNode("div", _hoisted_2, [createElementVNode("span", _hoisted_3, toDisplayString(model.value ? __props.labels?.[model.value] ?? model.value : model.value), 1), createVNode(unref(ScalarIcon), {
|
|
62
56
|
icon: "FilterList",
|
|
63
57
|
size: "md",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SectionFilter.vue.script.js","names":[],"sources":["../../src/components/SectionFilter.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"T extends string\">\nimport { ScalarIcon } from '@scalar/components/icon'\nimport { nextTick, ref } from 'vue'\n\nimport SectionFilterButton from '@/components/SectionFilterButton.vue'\nimport { useLocalization } from '@/v2/features/localization'\n\nconst {
|
|
1
|
+
{"version":3,"file":"SectionFilter.vue.script.js","names":[],"sources":["../../src/components/SectionFilter.vue"],"sourcesContent":["<script setup lang=\"ts\" generic=\"T extends string\">\nimport { ScalarIcon } from '@scalar/components/icon'\nimport { nextTick, ref } from 'vue'\n\nimport SectionFilterButton from '@/components/SectionFilterButton.vue'\nimport { useLocalization } from '@/v2/features/localization'\n\nconst { filters = [], labels } = defineProps<{\n filters?: T[]\n /** Localized labels keyed by stable filter IDs. */\n labels?: Partial<Record<T, string>>\n}>()\n\nconst model = defineModel<T>()\n\nconst tablist = ref<HTMLDivElement>()\nconst { direction } = useLocalization()\n\n/** Keyboard navigation */\nconst navigateSection = (arrow: 'left' | 'right'): void => {\n // Flex rows reverse in RTL, so the visual arrow direction reverses the index step.\n const offset =\n (arrow === 'left' ? -1 : 1) * (direction.value === 'rtl' ? -1 : 1)\n const index = model.value ? filters.indexOf(model.value) : 0\n const length = filters.length\n\n // Ensures we loop around the array by using the remainder\n const newIndex = (index + offset + length) % length\n model.value = filters[newIndex]\n\n // Focus the selected button\n nextTick(() => {\n if (tablist.value) {\n const selectedButton = tablist.value.querySelector(\n `button[aria-selected=\"true\"]`,\n ) satisfies HTMLButtonElement | null\n if (selectedButton) {\n selectedButton.focus()\n }\n }\n })\n}\n</script>\n<template>\n <div\n ref=\"tablist\"\n class=\"filter-hover context-bar-group ms-auto hidden lg:flex\"\n role=\"tablist\"\n @keydown.left=\"navigateSection('left')\"\n @keydown.right=\"navigateSection('right')\">\n <div\n class=\"request-section-content request-section-content-filter fade-request-section-content text-c-3 pointer-events-auto relative hidden w-full justify-end gap-[1.5px] rounded py-1.75 text-xs xl:flex\">\n <SectionFilterButton\n v-for=\"filter in filters\"\n :key=\"filter\"\n class=\"filter-hover-item\"\n role=\"tab\"\n :selected=\"model === filter\"\n @click=\"model = filter\">\n {{ labels?.[filter] ?? filter }}\n </SectionFilterButton>\n <div\n class=\"filter-button context-bar-group-hover:text-c-1 absolute -end-[30px] flex items-center\">\n <span class=\"context-bar-group-hover:hidden me-1.5\">{{\n model ? (labels?.[model] ?? model) : model\n }}</span>\n <ScalarIcon\n icon=\"FilterList\"\n size=\"md\"\n thickness=\"2\" />\n </div>\n </div>\n </div>\n</template>\n<style scoped>\n.fade-request-section-content {\n background: linear-gradient(\n to left,\n var(--scalar-background-1) 64%,\n transparent\n );\n}\n.fade-request-section-content:dir(rtl) {\n background: linear-gradient(\n to right,\n var(--scalar-background-1) 64%,\n transparent\n );\n}\n.filter-hover {\n height: 100%;\n padding-inline-end: 39px;\n padding-inline-start: 24px;\n position: absolute;\n inset-inline-end: 0;\n transition: width 0s ease-in-out 0.2s;\n overflow: hidden;\n}\n.filter-hover:hover,\n.filter-hover:has(:focus-visible) {\n width: 100%;\n z-index: 10;\n}\n.filter-hover:before {\n content: '';\n position: absolute;\n top: 0;\n inset-inline-start: 0;\n width: 100%;\n height: fit-content;\n background-color: var(--scalar-background-1);\n opacity: 0;\n transition: all 0.3s ease-in-out;\n pointer-events: none;\n}\n.filter-hover-item {\n opacity: 0;\n}\n.filter-hover-item:not(:last-of-type) {\n transform: translate3d(0, 3px, 0);\n}\n.filter-hover:hover .filter-hover-item {\n transition:\n opacity 0.2s ease-in-out,\n transform 0.2s ease-in-out;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(1) {\n transition-delay: 0.05s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(2) {\n transition-delay: 0.1s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(3) {\n transition-delay: 0.15s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(4) {\n transition-delay: 0.2s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(5) {\n transition-delay: 0.25s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(6) {\n transition-delay: 0.3s;\n}\n.filter-hover:hover .filter-hover-item:nth-last-of-type(7) {\n transition-delay: 0.35s;\n}\n.filter-hover:hover .filter-hover-item,\n.filter-hover:has(:focus-visible) .filter-hover-item {\n opacity: 1;\n transform: translate3d(0, 0, 0);\n}\n.filter-hover:hover:before,\n.filter-hover:has(:focus-visible):before {\n opacity: 0.9;\n backdrop-filter: blur(10px);\n}\n.filter-button {\n top: 50%;\n transform: translateY(-50%);\n}\n.context-bar-group:hover .context-bar-group-hover\\:text-c-1,\n.context-bar-group:has(:focus-visible) .context-bar-group-hover\\:text-c-1 {\n --tw-text-opacity: 1;\n color: rgb(var(--scalar-color-1) / var(--tw-text-opacity));\n}\n\n.context-bar-group:hover .context-bar-group-hover\\:hidden,\n.context-bar-group:has(:focus-visible) .context-bar-group-hover\\:hidden {\n display: none;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;EAaA,MAAM,QAAQ,SAAc,SAAA,YAAC;EAE7B,MAAM,UAAU,IAAoB;EACpC,MAAM,EAAE,cAAc,gBAAgB;;EAGtC,MAAM,mBAAmB,UAAkC;GAEzD,MAAM,UACH,UAAU,SAAS,KAAK,MAAM,UAAU,UAAU,QAAQ,KAAK;GAClE,MAAM,QAAQ,MAAM,QAAQ,QAAA,QAAQ,QAAQ,MAAM,KAAK,IAAI;GAC3D,MAAM,SAAS,QAAA,QAAQ;GAGvB,MAAM,YAAY,QAAQ,SAAS,UAAU;GAC7C,MAAM,QAAQ,QAAA,QAAQ;GAGtB,eAAe;IACb,IAAI,QAAQ,OAAO;KACjB,MAAM,iBAAiB,QAAQ,MAAM,cACnC,8BACF;KACA,IAAI,gBACF,eAAe,MAAM;IAEzB;GACF,CAAC;EACH;;uBAGE,mBA4BM,OAAA;aA3BA;IAAJ,KAAI;IACJ,OAAM;IACN,MAAK;IACJ,WAAO,CAAA,OAAA,OAAA,OAAA,KAAA,UAAA,WAAO,gBAAe,MAAA,GAAA,CAAA,MAAA,CAAA,IAAA,OAAA,OAAA,OAAA,KAAA,UAAA,WACd,gBAAe,OAAA,GAAA,CAAA,OAAA,CAAA,EAAA;OAC/B,mBAqBM,OArBN,YAqBM,EAAA,UAAA,IAAA,GAnBJ,mBAQsB,UAAA,MAAA,WAPH,QAAA,UAAV,WAAM;wBADf,YAQsB,6BAAA;KANnB,KAAK;KACN,OAAM;KACN,MAAK;KACJ,UAAU,MAAA,UAAU;KACpB,UAAK,WAAE,MAAA,QAAQ;;4BACgB,CAAA,gBAAA,gBAA7B,QAAA,SAAS,WAAW,MAAM,GAAA,CAAA,CAAA,CAAA;;;cAE/B,mBASM,OATN,YASM,CAPJ,mBAES,QAFT,YAES,gBADP,MAAA,QAAS,QAAA,SAAS,MAAA,UAAU,MAAA,QAAS,MAAA,KAAK,GAAA,CAAA,GAE5C,YAGkB,MAAA,UAAA,GAAA;IAFhB,MAAK;IACL,MAAK;IACL,WAAU"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SectionFilterButton.vue.d.ts","sourceRoot":"","sources":["../../src/components/SectionFilterButton.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SectionFilterButton.vue.d.ts","sourceRoot":"","sources":["../../src/components/SectionFilterButton.vue"],"names":[],"mappings":"AA0BA,KAAK,WAAW,GAAG;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAC;AA0CF,QAAA,IAAI,OAAO,IAAW,CAAE;AACxB,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,CAAC;AAG/C,QAAA,MAAM,UAAU,kSAEd,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AACzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SectionFilterButton.vue.js","names":[],"sources":["../../src/components/SectionFilterButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\nconst { selected
|
|
1
|
+
{"version":3,"file":"SectionFilterButton.vue.js","names":[],"sources":["../../src/components/SectionFilterButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\nconst { selected } = defineProps<{\n selected?: boolean\n}>()\n</script>\n<template>\n <!--\n Deliberately no aria-controls. While the focused tab controls a visible\n panel, NVDA re-announces every tab whose aria-selected changes (Chromium\n fires a selection event, see nvaccess/nvda#18794), so arrow keys read\n \"Auth tab selected 2 of 6\" twice. Screen readers do not need the relation\n to convey the tabs' name, role and state.\n -->\n <button\n :aria-selected=\"!!selected\"\n class=\"hover:bg-b-2 flex w-fit cursor-pointer items-center rounded p-1 px-2 text-center font-medium whitespace-nowrap has-[:focus-visible]:outline\"\n :class=\"{ 'text-c-1 pointer-events-none': selected }\"\n role=\"tab\"\n :tabindex=\"selected ? 0 : -1\"\n type=\"button\">\n <slot />\n </button>\n</template>\n"],"mappings":""}
|
|
@@ -1,20 +1,12 @@
|
|
|
1
1
|
import { createElementBlock, defineComponent, normalizeClass, openBlock, renderSlot } from "vue";
|
|
2
2
|
//#region src/components/SectionFilterButton.vue?vue&type=script&setup=true&lang.ts
|
|
3
|
-
var _hoisted_1 = [
|
|
4
|
-
"aria-controls",
|
|
5
|
-
"aria-selected",
|
|
6
|
-
"tabindex"
|
|
7
|
-
];
|
|
3
|
+
var _hoisted_1 = ["aria-selected", "tabindex"];
|
|
8
4
|
var SectionFilterButton_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
|
|
9
5
|
__name: "SectionFilterButton",
|
|
10
|
-
props: {
|
|
11
|
-
selected: { type: Boolean },
|
|
12
|
-
controls: {}
|
|
13
|
-
},
|
|
6
|
+
props: { selected: { type: Boolean } },
|
|
14
7
|
setup(__props) {
|
|
15
8
|
return (_ctx, _cache) => {
|
|
16
9
|
return openBlock(), createElementBlock("button", {
|
|
17
|
-
"aria-controls": __props.controls ?? "",
|
|
18
10
|
"aria-selected": !!__props.selected,
|
|
19
11
|
class: normalizeClass(["hover:bg-b-2 flex w-fit cursor-pointer items-center rounded p-1 px-2 text-center font-medium whitespace-nowrap has-[:focus-visible]:outline", { "text-c-1 pointer-events-none": __props.selected }]),
|
|
20
12
|
role: "tab",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SectionFilterButton.vue.script.js","names":[],"sources":["../../src/components/SectionFilterButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\nconst { selected
|
|
1
|
+
{"version":3,"file":"SectionFilterButton.vue.script.js","names":[],"sources":["../../src/components/SectionFilterButton.vue"],"sourcesContent":["<script setup lang=\"ts\">\nconst { selected } = defineProps<{\n selected?: boolean\n}>()\n</script>\n<template>\n <!--\n Deliberately no aria-controls. While the focused tab controls a visible\n panel, NVDA re-announces every tab whose aria-selected changes (Chromium\n fires a selection event, see nvaccess/nvda#18794), so arrow keys read\n \"Auth tab selected 2 of 6\" twice. Screen readers do not need the relation\n to convey the tabs' name, role and state.\n -->\n <button\n :aria-selected=\"!!selected\"\n class=\"hover:bg-b-2 flex w-fit cursor-pointer items-center rounded p-1 px-2 text-center font-medium whitespace-nowrap has-[:focus-visible]:outline\"\n :class=\"{ 'text-c-1 pointer-events-none': selected }\"\n role=\"tab\"\n :tabindex=\"selected ? 0 : -1\"\n type=\"button\">\n <slot />\n </button>\n</template>\n"],"mappings":";;;;;;;;uBAaE,mBAQS,UAAA;IAPN,iBAAa,CAAA,CAAI,QAAA;IAClB,OAAK,eAAA,CAAC,+IAA6I,EAAA,gCACzG,QAAA,SAAQ,CAAA,CAAA;IAClD,MAAK;IACJ,UAAU,QAAA,WAAQ,IAAA;IACnB,MAAK;OACL,WAAQ,KAAA,QAAA,SAAA,CAAA,GAAA,IAAA,UAAA"}
|