🚨 Latest Research:Tanstack npm Packages Compromised in Ongoing Mini Shai-Hulud Supply-Chain Attack.Learn More
Socket
Book a DemoSign in
Socket

@scalar/api-client

Package Overview
Dependencies
Maintainers
8
Versions
526
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@scalar/api-client - npm Package Compare versions

Comparing version
3.1.0
to
3.2.0
+15
dist/v2/types/options.d.ts
import type { CustomFetch } from '../../v2/blocks/operation-block/helpers/send-request.js';
import type { ApiReferenceConfigurationRaw } from '@scalar/types/api-reference';
import type { Ref } from 'vue';
/**
* Configuration options for the API Client (app and modal).
*/
export type ApiClientOptions = Partial<Pick<ApiReferenceConfigurationRaw, 'authentication' | 'baseServerURL' | 'hideClientButton' | 'hiddenClients' | 'oauth2RedirectUri' | 'proxyUrl' | 'servers'>> & {
/**
* Custom fetch implementation used for all outgoing API requests.
* When provided, replaces the global fetch in the request execution engine (sendRequest).
*/
customFetch?: CustomFetch;
};
export type ApiClientOptionsRef = Ref<ApiClientOptions>;
//# sourceMappingURL=options.d.ts.map
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../../src/v2/types/options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAA;AACnF,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,6BAA6B,CAAA;AAC/E,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAE9B;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,OAAO,CACpC,IAAI,CACF,4BAA4B,EAC1B,gBAAgB,GAChB,eAAe,GACf,kBAAkB,GAClB,eAAe,GACf,mBAAmB,GACnB,UAAU,GACV,SAAS,CACZ,CACF,GAAG;IACF;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG,GAAG,CAAC,gBAAgB,CAAC,CAAA"}
+2
-2

@@ -7,5 +7,5 @@ type __VLS_Props = {

declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
change: (value: "delete" | "head" | "get" | "options" | "put" | "post" | "patch" | "trace") => any;
change: (value: "head" | "delete" | "get" | "options" | "patch" | "post" | "put" | "trace") => any;
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
onChange?: ((value: "delete" | "head" | "get" | "options" | "put" | "post" | "patch" | "trace") => any) | undefined;
onChange?: ((value: "head" | "delete" | "get" | "options" | "patch" | "post" | "put" | "trace") => any) | undefined;
}>, {

@@ -12,0 +12,0 @@ isSquare: boolean;

@@ -10,7 +10,7 @@ type __VLS_Props = {

declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
cancel: () => any;
submit: () => any;
cancel: () => any;
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
onCancel?: (() => any) | undefined;
onSubmit?: (() => any) | undefined;
onCancel?: (() => any) | undefined;
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;

@@ -17,0 +17,0 @@ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;

@@ -30,2 +30,4 @@ import { type ErrorResponse } from '@scalar/helpers/errors/normalize-error';

});
/** Custom fetch function signature compatible with the global fetch API */
export type CustomFetch = typeof fetch;
/**

@@ -44,3 +46,3 @@ * Execute the built fetch request and return a structured response.

*/
export declare const sendRequest: ({ isUsingProxy, requestPayload, plugins, }: {
export declare const sendRequest: ({ isUsingProxy, requestPayload, plugins, customFetch, }: {
isUsingProxy: boolean;

@@ -50,2 +52,4 @@ requestPayload: RequestPayload;

plugins?: ClientPlugin[];
/** Optional custom fetch implementation, overrides the global fetch */
customFetch?: CustomFetch;
}) => Promise<ErrorResponse<{

@@ -52,0 +56,0 @@ response: ResponseInstance;

@@ -1,1 +0,1 @@

{"version":3,"file":"send-request.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/operation-block/helpers/send-request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,aAAa,EAAkB,MAAM,wCAAwC,CAAA;AAGnG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AAGnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAA;AAe7E,0DAA0D;AAC1D,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG;IACzD,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,wCAAwC;IACxC,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAA;IAChB,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAA;IAClB,0BAA0B;IAC1B,MAAM,EAAE,UAAU,CAAA;IAClB,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAA;CACb,GAAG,CACE;IACE,wBAAwB;IACxB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAA;CACb,GACD;IACE,qDAAqD;IACrD,MAAM,EAAE,2BAA2B,CAAC,UAAU,CAAC,CAAA;CAChD,CACJ,CAAA;AAKH;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,GAAU,4CAI/B;IACD,YAAY,EAAE,OAAO,CAAA;IACrB,cAAc,EAAE,cAAc,CAAA;IAC9B,iEAAiE;IACjE,OAAO,CAAC,EAAE,YAAY,EAAE,CAAA;CACzB,KAAG,OAAO,CACT,aAAa,CAAC;IACZ,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,cAAc,EAAE,cAAc,CAAA;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,gBAAgB,EAAE,QAAQ,CAAA;CAC3B,CAAC,CA2DH,CAAA"}
{"version":3,"file":"send-request.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/operation-block/helpers/send-request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,aAAa,EAAkB,MAAM,wCAAwC,CAAA;AAGnG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AAGnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAA;AAe7E,0DAA0D;AAC1D,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG;IACzD,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,wCAAwC;IACxC,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAA;IAChB,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAA;IAClB,0BAA0B;IAC1B,MAAM,EAAE,UAAU,CAAA;IAClB,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAA;CACb,GAAG,CACE;IACE,wBAAwB;IACxB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAA;CACb,GACD;IACE,qDAAqD;IACrD,MAAM,EAAE,2BAA2B,CAAC,UAAU,CAAC,CAAA;CAChD,CACJ,CAAA;AAKH,2EAA2E;AAC3E,MAAM,MAAM,WAAW,GAAG,OAAO,KAAK,CAAA;AAEtC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,GAAU,yDAK/B;IACD,YAAY,EAAE,OAAO,CAAA;IACrB,cAAc,EAAE,cAAc,CAAA;IAC9B,iEAAiE;IACjE,OAAO,CAAC,EAAE,YAAY,EAAE,CAAA;IACxB,uEAAuE;IACvE,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B,KAAG,OAAO,CACT,aAAa,CAAC;IACZ,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,cAAc,EAAE,cAAc,CAAA;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,gBAAgB,EAAE,QAAQ,CAAA;CAC3B,CAAC,CA0DH,CAAA"}

@@ -33,6 +33,6 @@ import { getCookieHeaderKeys } from "./get-cookie-header-keys.js";

*/
var sendRequest = async ({ isUsingProxy, requestPayload, plugins = [] }) => {
var sendRequest = async ({ isUsingProxy, requestPayload, plugins = [], customFetch = fetch }) => {
try {
const startTime = performance.now();
const response = isElectron() && window.proxiedFetch ? await window.proxiedFetch?.(...requestPayload) : await fetch(buildSafeBodyRequest(...requestPayload));
const response = isElectron() ? await customFetch(...requestPayload) : await customFetch(buildSafeBodyRequest(...requestPayload));
const endTime = performance.now();

@@ -39,0 +39,0 @@ const timestamp = Date.now();

@@ -1,1 +0,1 @@

{"version":3,"file":"send-request.js","names":[],"sources":["../../../../../src/v2/blocks/operation-block/helpers/send-request.ts"],"sourcesContent":["import { ERRORS, type ErrorResponse, normalizeError } from '@scalar/helpers/errors/normalize-error'\nimport { isElectron } from '@scalar/helpers/general/is-electron'\nimport { buildSafeBodyRequest } from '@scalar/helpers/http/can-method-have-body'\nimport type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport { httpStatusCodes } from '@scalar/helpers/http/http-status-codes'\nimport { normalizeHeaders } from '@scalar/helpers/http/normalize-headers'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport type { RequestPayload } from '@scalar/workspace-store/request-example'\nimport * as cookie from 'cookie'\nimport { parseSetCookie } from 'set-cookie-parser'\n\nimport { getCookieHeaderKeys } from '@/v2/blocks/operation-block/helpers/get-cookie-header-keys'\nimport { resolveResponseBodyHandler } from '@/v2/blocks/response-block/helpers/resolve-response-body-handler'\nimport {\n resolveResponseContentType,\n resolveResponseMimeType,\n} from '@/v2/blocks/response-block/helpers/resolve-response-content-type'\n\nimport { decodeBuffer } from './decode-buffer'\n\nconst CUSTOM_COOKIE_HEADER = 'x-scalar-set-cookie'\n\n/** A single set of populated values for a sent request */\nexport type ResponseInstance = Omit<Response, 'headers'> & {\n /** Store headers as an object to match what we had with axios */\n headers: Record<string, string>\n /** Keys of headers which set cookies */\n cookieHeaderKeys: string[]\n /** Time in ms the request took */\n duration: number\n /** The response status */\n status: number\n /** The response status text */\n statusText: string\n /** The response method */\n method: HttpMethod\n /** The request path */\n path: string\n} & (\n | {\n /** The response data */\n data: string | Blob\n /** The response size in bytes */\n size: number\n }\n | {\n /** A stream reader for a streamable response body */\n reader: ReadableStreamDefaultReader<Uint8Array>\n }\n )\n\n/** HTTP status codes that should not include a response body */\nconst NO_BODY_STATUS_CODES = [204, 205, 304]\n\n/**\n * Execute the built fetch request and return a structured response.\n *\n * This function handles the complete request lifecycle including plugin hooks,\n * response processing, streaming detection, and error handling. It supports both\n * standard responses and server-sent event streams.\n *\n * @param request - The request built by the buildRequest helper\n * @param operation - The OpenAPI operation being executed\n * @param plugins - Array of client plugins to execute hooks\n * @param isUsingProxy - Whether the request is being proxied for header handling\n * @returns A tuple with either an error or the response data\n */\nexport const sendRequest = async ({\n isUsingProxy,\n requestPayload,\n plugins = [],\n}: {\n isUsingProxy: boolean\n requestPayload: RequestPayload\n /** Registered client plugins for custom content type handling */\n plugins?: ClientPlugin[]\n}): Promise<\n ErrorResponse<{\n response: ResponseInstance\n requestPayload: RequestPayload\n timestamp: number\n originalResponse: Response\n }>\n> => {\n try {\n // Execute the request and measure duration\n const startTime = performance.now()\n\n // We may use a custom fetch function on electron\n const response =\n isElectron() && window.proxiedFetch\n ? await window.proxiedFetch?.(...requestPayload)\n : await fetch(buildSafeBodyRequest(...requestPayload))\n\n const endTime = performance.now()\n const timestamp = Date.now()\n const duration = endTime - startTime\n\n // Extract response metadata early for reuse\n const contentType = response.headers.get('content-type')\n const responseHeaders = normalizeHeaders(response.headers, isUsingProxy)\n const responseUrl = new URL(response.url)\n const fullPath = responseUrl.pathname + responseUrl.search\n const statusText = response.statusText || httpStatusCodes[response.status]?.name || ''\n const method = (requestPayload[1].method ?? 'GET') as HttpMethod\n const shouldSkipBody = NO_BODY_STATUS_CODES.includes(response.status)\n\n /**\n * Handle server-sent event streams separately.\n * These responses need a reader instead of buffered data.\n * We check this early to avoid unnecessary body reading.\n */\n if (contentType?.startsWith('text/event-stream') && response.body) {\n return buildStreamingResponse({\n response,\n requestPayload,\n timestamp,\n duration,\n responseHeaders,\n statusText,\n method,\n fullPath,\n })\n }\n\n return buildStandardResponse({\n response,\n requestPayload,\n timestamp,\n duration,\n responseHeaders,\n statusText,\n method,\n fullPath,\n contentType,\n shouldSkipBody,\n plugins,\n })\n } catch (error) {\n return [normalizeError(error, ERRORS.REQUEST_FAILED), null]\n }\n}\n\n/**\n * Extracts and serializes custom cookies from the response using the custom cookie header.\n *\n * This function parses the custom cookie header (if present), serializes each cookie using the\n * 'cookie' library, and then deletes the custom cookie header from the response.\n * Returns an array of serialized cookie strings, or null if no cookies were found.\n *\n * The @ts-expect-error is present due to a type mismatch between the 'cookie' parsing and serialization libraries.\n */\nconst getCustomCookie = (response: Response): string[] | null => {\n const result = parseSetCookie(response.headers.get(CUSTOM_COOKIE_HEADER) ?? '').map((c) =>\n cookie.serialize(c.name, c.value, {\n ...c,\n sameSite: c.sameSite as boolean | 'lax' | 'strict' | 'none' | undefined,\n encode: (str: string) => str,\n }),\n )\n\n if (result.length) {\n return result\n }\n\n return null\n}\n\n/**\n * Build a streaming response for server-sent events.\n * Streaming responses use a reader instead of buffering the entire body.\n */\nconst buildStreamingResponse = ({\n response,\n requestPayload,\n timestamp,\n duration,\n responseHeaders,\n statusText,\n method,\n fullPath,\n}: {\n response: Response\n requestPayload: RequestPayload\n timestamp: number\n duration: number\n responseHeaders: Record<string, string>\n statusText: string\n method: HttpMethod\n fullPath: string\n}): ErrorResponse<{\n response: ResponseInstance\n requestPayload: RequestPayload\n timestamp: number\n originalResponse: Response\n}> => {\n const normalizedResponse = new Response(null, {\n status: response.status,\n statusText,\n headers: response.headers,\n })\n\n const customCookie = getCustomCookie(normalizedResponse)\n const cookieHeaderKeys = customCookie ?? getCookieHeaderKeys(normalizedResponse.headers)\n\n return [\n null,\n {\n timestamp,\n requestPayload,\n response: {\n ...normalizedResponse,\n headers: responseHeaders,\n cookieHeaderKeys,\n reader: response.body!.getReader(),\n duration,\n method,\n path: fullPath,\n },\n originalResponse: normalizedResponse.clone(),\n },\n ]\n}\n\n/**\n * Build a standard response with buffered body data.\n * This handles all non-streaming responses including JSON, text, and binary data.\n */\nconst buildStandardResponse = async ({\n response,\n requestPayload,\n timestamp,\n duration,\n responseHeaders,\n statusText,\n method,\n fullPath,\n contentType,\n shouldSkipBody,\n plugins,\n}: {\n response: Response\n requestPayload: RequestPayload\n timestamp: number\n duration: number\n responseHeaders: Record<string, string>\n statusText: string\n method: HttpMethod\n fullPath: string\n contentType: string | null\n shouldSkipBody: boolean\n plugins: ClientPlugin[]\n}): Promise<\n ErrorResponse<{\n response: ResponseInstance\n requestPayload: RequestPayload\n timestamp: number\n originalResponse: Response\n }>\n> => {\n /**\n * Clone the response to preserve the original for body reading.\n * Read the body once and reuse the buffer for both decoding and creating a new Response.\n */\n const clonedResponse = response.clone()\n const arrayBuffer = await clonedResponse.arrayBuffer()\n const responseType = resolveResponseContentType(contentType)\n const mimeEssence = resolveResponseMimeType(contentType).essence\n const pluginHandler = resolveResponseBodyHandler(mimeEssence, plugins)\n const responseData = await decodeBuffer(arrayBuffer, responseType, pluginHandler)\n\n /**\n * Create a new Response using the arrayBuffer we already read.\n * ArrayBuffers can be reused to create new Response objects without additional memory.\n */\n const normalizedResponse = new Response(shouldSkipBody ? null : arrayBuffer, {\n status: response.status,\n statusText,\n headers: response.headers,\n })\n\n const customCookie = getCustomCookie(normalizedResponse)\n const cookieHeaderKeys = customCookie ?? getCookieHeaderKeys(normalizedResponse.headers)\n\n return [\n null,\n {\n timestamp,\n requestPayload,\n response: {\n ...normalizedResponse,\n headers: responseHeaders,\n cookieHeaderKeys,\n data: responseData,\n size: arrayBuffer.byteLength,\n duration,\n method,\n status: response.status,\n path: fullPath,\n },\n originalResponse: response.clone(),\n },\n ]\n}\n"],"mappings":"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"}
{"version":3,"file":"send-request.js","names":[],"sources":["../../../../../src/v2/blocks/operation-block/helpers/send-request.ts"],"sourcesContent":["import { ERRORS, type ErrorResponse, normalizeError } from '@scalar/helpers/errors/normalize-error'\nimport { isElectron } from '@scalar/helpers/general/is-electron'\nimport { buildSafeBodyRequest } from '@scalar/helpers/http/can-method-have-body'\nimport type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport { httpStatusCodes } from '@scalar/helpers/http/http-status-codes'\nimport { normalizeHeaders } from '@scalar/helpers/http/normalize-headers'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport type { RequestPayload } from '@scalar/workspace-store/request-example'\nimport * as cookie from 'cookie'\nimport { parseSetCookie } from 'set-cookie-parser'\n\nimport { getCookieHeaderKeys } from '@/v2/blocks/operation-block/helpers/get-cookie-header-keys'\nimport { resolveResponseBodyHandler } from '@/v2/blocks/response-block/helpers/resolve-response-body-handler'\nimport {\n resolveResponseContentType,\n resolveResponseMimeType,\n} from '@/v2/blocks/response-block/helpers/resolve-response-content-type'\n\nimport { decodeBuffer } from './decode-buffer'\n\nconst CUSTOM_COOKIE_HEADER = 'x-scalar-set-cookie'\n\n/** A single set of populated values for a sent request */\nexport type ResponseInstance = Omit<Response, 'headers'> & {\n /** Store headers as an object to match what we had with axios */\n headers: Record<string, string>\n /** Keys of headers which set cookies */\n cookieHeaderKeys: string[]\n /** Time in ms the request took */\n duration: number\n /** The response status */\n status: number\n /** The response status text */\n statusText: string\n /** The response method */\n method: HttpMethod\n /** The request path */\n path: string\n} & (\n | {\n /** The response data */\n data: string | Blob\n /** The response size in bytes */\n size: number\n }\n | {\n /** A stream reader for a streamable response body */\n reader: ReadableStreamDefaultReader<Uint8Array>\n }\n )\n\n/** HTTP status codes that should not include a response body */\nconst NO_BODY_STATUS_CODES = [204, 205, 304]\n\n/** Custom fetch function signature compatible with the global fetch API */\nexport type CustomFetch = typeof fetch\n\n/**\n * Execute the built fetch request and return a structured response.\n *\n * This function handles the complete request lifecycle including plugin hooks,\n * response processing, streaming detection, and error handling. It supports both\n * standard responses and server-sent event streams.\n *\n * @param request - The request built by the buildRequest helper\n * @param operation - The OpenAPI operation being executed\n * @param plugins - Array of client plugins to execute hooks\n * @param isUsingProxy - Whether the request is being proxied for header handling\n * @returns A tuple with either an error or the response data\n */\nexport const sendRequest = async ({\n isUsingProxy,\n requestPayload,\n plugins = [],\n customFetch = fetch,\n}: {\n isUsingProxy: boolean\n requestPayload: RequestPayload\n /** Registered client plugins for custom content type handling */\n plugins?: ClientPlugin[]\n /** Optional custom fetch implementation, overrides the global fetch */\n customFetch?: CustomFetch\n}): Promise<\n ErrorResponse<{\n response: ResponseInstance\n requestPayload: RequestPayload\n timestamp: number\n originalResponse: Response\n }>\n> => {\n try {\n // Execute the request and measure duration\n const startTime = performance.now()\n\n // In electron we allow GET requests to have a body\n const response = isElectron()\n ? await customFetch(...requestPayload)\n : await customFetch(buildSafeBodyRequest(...requestPayload))\n\n const endTime = performance.now()\n const timestamp = Date.now()\n const duration = endTime - startTime\n\n // Extract response metadata early for reuse\n const contentType = response.headers.get('content-type')\n const responseHeaders = normalizeHeaders(response.headers, isUsingProxy)\n const responseUrl = new URL(response.url)\n const fullPath = responseUrl.pathname + responseUrl.search\n const statusText = response.statusText || httpStatusCodes[response.status]?.name || ''\n const method = (requestPayload[1].method ?? 'GET') as HttpMethod\n const shouldSkipBody = NO_BODY_STATUS_CODES.includes(response.status)\n\n /**\n * Handle server-sent event streams separately.\n * These responses need a reader instead of buffered data.\n * We check this early to avoid unnecessary body reading.\n */\n if (contentType?.startsWith('text/event-stream') && response.body) {\n return buildStreamingResponse({\n response,\n requestPayload,\n timestamp,\n duration,\n responseHeaders,\n statusText,\n method,\n fullPath,\n })\n }\n\n return buildStandardResponse({\n response,\n requestPayload,\n timestamp,\n duration,\n responseHeaders,\n statusText,\n method,\n fullPath,\n contentType,\n shouldSkipBody,\n plugins,\n })\n } catch (error) {\n return [normalizeError(error, ERRORS.REQUEST_FAILED), null]\n }\n}\n\n/**\n * Extracts and serializes custom cookies from the response using the custom cookie header.\n *\n * This function parses the custom cookie header (if present), serializes each cookie using the\n * 'cookie' library, and then deletes the custom cookie header from the response.\n * Returns an array of serialized cookie strings, or null if no cookies were found.\n *\n * The @ts-expect-error is present due to a type mismatch between the 'cookie' parsing and serialization libraries.\n */\nconst getCustomCookie = (response: Response): string[] | null => {\n const result = parseSetCookie(response.headers.get(CUSTOM_COOKIE_HEADER) ?? '').map((c) =>\n cookie.serialize(c.name, c.value, {\n ...c,\n sameSite: c.sameSite as boolean | 'lax' | 'strict' | 'none' | undefined,\n encode: (str: string) => str,\n }),\n )\n\n if (result.length) {\n return result\n }\n\n return null\n}\n\n/**\n * Build a streaming response for server-sent events.\n * Streaming responses use a reader instead of buffering the entire body.\n */\nconst buildStreamingResponse = ({\n response,\n requestPayload,\n timestamp,\n duration,\n responseHeaders,\n statusText,\n method,\n fullPath,\n}: {\n response: Response\n requestPayload: RequestPayload\n timestamp: number\n duration: number\n responseHeaders: Record<string, string>\n statusText: string\n method: HttpMethod\n fullPath: string\n}): ErrorResponse<{\n response: ResponseInstance\n requestPayload: RequestPayload\n timestamp: number\n originalResponse: Response\n}> => {\n const normalizedResponse = new Response(null, {\n status: response.status,\n statusText,\n headers: response.headers,\n })\n\n const customCookie = getCustomCookie(normalizedResponse)\n const cookieHeaderKeys = customCookie ?? getCookieHeaderKeys(normalizedResponse.headers)\n\n return [\n null,\n {\n timestamp,\n requestPayload,\n response: {\n ...normalizedResponse,\n headers: responseHeaders,\n cookieHeaderKeys,\n reader: response.body!.getReader(),\n duration,\n method,\n path: fullPath,\n },\n originalResponse: normalizedResponse.clone(),\n },\n ]\n}\n\n/**\n * Build a standard response with buffered body data.\n * This handles all non-streaming responses including JSON, text, and binary data.\n */\nconst buildStandardResponse = async ({\n response,\n requestPayload,\n timestamp,\n duration,\n responseHeaders,\n statusText,\n method,\n fullPath,\n contentType,\n shouldSkipBody,\n plugins,\n}: {\n response: Response\n requestPayload: RequestPayload\n timestamp: number\n duration: number\n responseHeaders: Record<string, string>\n statusText: string\n method: HttpMethod\n fullPath: string\n contentType: string | null\n shouldSkipBody: boolean\n plugins: ClientPlugin[]\n}): Promise<\n ErrorResponse<{\n response: ResponseInstance\n requestPayload: RequestPayload\n timestamp: number\n originalResponse: Response\n }>\n> => {\n /**\n * Clone the response to preserve the original for body reading.\n * Read the body once and reuse the buffer for both decoding and creating a new Response.\n */\n const clonedResponse = response.clone()\n const arrayBuffer = await clonedResponse.arrayBuffer()\n const responseType = resolveResponseContentType(contentType)\n const mimeEssence = resolveResponseMimeType(contentType).essence\n const pluginHandler = resolveResponseBodyHandler(mimeEssence, plugins)\n const responseData = await decodeBuffer(arrayBuffer, responseType, pluginHandler)\n\n /**\n * Create a new Response using the arrayBuffer we already read.\n * ArrayBuffers can be reused to create new Response objects without additional memory.\n */\n const normalizedResponse = new Response(shouldSkipBody ? null : arrayBuffer, {\n status: response.status,\n statusText,\n headers: response.headers,\n })\n\n const customCookie = getCustomCookie(normalizedResponse)\n const cookieHeaderKeys = customCookie ?? getCookieHeaderKeys(normalizedResponse.headers)\n\n return [\n null,\n {\n timestamp,\n requestPayload,\n response: {\n ...normalizedResponse,\n headers: responseHeaders,\n cookieHeaderKeys,\n data: responseData,\n size: arrayBuffer.byteLength,\n duration,\n method,\n status: response.status,\n path: fullPath,\n },\n originalResponse: response.clone(),\n },\n ]\n}\n"],"mappings":"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"}

@@ -1,1 +0,1 @@

{"version":3,"file":"OperationBlock.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/blocks/operation-block/OperationBlock.vue"],"names":[],"mappings":"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"}
{"version":3,"file":"OperationBlock.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/blocks/operation-block/OperationBlock.vue"],"names":[],"mappings":"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"}

@@ -1,1 +0,1 @@

{"version":3,"file":"OperationBlock.vue.js","names":[],"sources":["../../../../src/v2/blocks/operation-block/OperationBlock.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * OperationBlock\n *\n * Orchestrates the operation view by wiring together the Header, OperationBlock,\n * and ResponseBlock. Forwards user interactions to the workspace event bus and\n * passes through configuration such as auth, servers, plugins, and environment.\n * This component keeps the Operation page lean by centralizing event emission\n * and prop wiring between the blocks.\n *\n * Notable behavior:\n * - Uses operation['x-scalar-method'] and operation['x-scalar-path'] to provide\n * draft overrides for the UI when present.\n */\nexport default {\n name: 'OperationBlock',\n}\n\nexport type OperationBlockProps = {\n /** Event bus */\n eventBus: WorkspaceEventBus\n /** Application version */\n appVersion: string\n /** Openapi document */\n document: OpenApiDocument\n /** Workspace cookies */\n workspaceCookies: XScalarCookie[]\n /** Document cookies */\n documentCookies: XScalarCookie[]\n /** Current request path */\n path: string\n /** Current request method */\n method: HttpMethodType\n /** HTTP clients */\n httpClients: AvailableClients\n /** The history for the operation */\n history?: HistoryEntry[]\n /** Client layout */\n layout: ClientLayout\n /** Currently selected server */\n server: ServerObject | null\n /** Currently selected client */\n selectedClient: WorkspaceStore['workspace']['x-scalar-default-client']\n /** Server list available for operation/document */\n servers: ServerObject[]\n /** Meta information for the server */\n serverMeta: ServerMeta\n /** Hides the client button on the header */\n hideClientButton?: boolean\n /** Client integration */\n integration?: string | null\n /** Openapi document url for `modal` mode to open the client app */\n documentUrl?: string\n /** Client source */\n source?: 'gitbook' | 'api-reference'\n /** Operation object */\n operation: OperationObject\n /** Currently selected example key for the current operation */\n exampleKey: string\n /** Meta information for the auth update */\n authMeta: AuthMeta\n /** Document defined security schemes */\n securitySchemes: MergedSecuritySchemes\n /** Client plugins */\n plugins: ClientPlugin[]\n /** Environment list */\n environments?: string[]\n /** Currently selected environment */\n activeEnvironment?: string\n /** For environment variables in the inputs */\n environment: XScalarEnvironment\n /** The proxy URL for sending requests */\n proxyUrl: string\n /** Currently selected security */\n selectedSecurity: SelectedSecurity\n /** Currently selected security schemes */\n selectedSecuritySchemes: SecuritySchemeObjectSecret[]\n /** Security requirements */\n securityRequirements: OpenApiDocument['security']\n /** Default headers */\n defaultHeaders: Record<string, string>\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection?: Record<string, number>\n /** Subset of config options for the modal */\n options?: ModalProps['options']\n}\n</script>\n<script setup lang=\"ts\">\nimport { ERRORS } from '@scalar/helpers/errors/normalize-error'\nimport { isElectron } from '@scalar/helpers/general/is-electron'\nimport { buildSafeBodyRequest } from '@scalar/helpers/http/can-method-have-body'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { executeHook, type ClientPlugin } from '@scalar/oas-utils/helpers'\nimport {\n AVAILABLE_CLIENTS,\n type AvailableClients,\n} from '@scalar/types/snippetz'\nimport { useToasts } from '@scalar/use-toasts'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { SelectedSecurity } from '@scalar/workspace-store/entities/auth'\nimport type { HistoryEntry } from '@scalar/workspace-store/entities/history/schema'\nimport type {\n AuthMeta,\n ServerMeta,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport {\n buildRequest,\n createVariablesStoreForRequest,\n getEnvironmentVariables,\n requestFactory,\n type MergedSecuritySchemes,\n type RequestPayload,\n type SecuritySchemeObjectSecret,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type {\n OpenApiDocument,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport type { OperationObject } from '@scalar/workspace-store/schemas/v3.1/strict/operation'\nimport { computed, onBeforeUnmount, onMounted, ref, toValue, watch } from 'vue'\n\nimport ViewLayout from '@/components/ViewLayout/ViewLayout.vue'\nimport ViewLayoutContent from '@/components/ViewLayout/ViewLayoutContent.vue'\nimport { harToFetchRequest } from '@/v2/blocks/operation-block/helpers/har-to-fetch-request'\nimport { harToFetchResponse } from '@/v2/blocks/operation-block/helpers/har-to-fetch-response'\nimport {\n getOperationExampleKey,\n isStreamingResponse,\n responseCache,\n} from '@/v2/blocks/operation-block/helpers/response-cache'\nimport {\n sendRequest,\n type ResponseInstance,\n} from '@/v2/blocks/operation-block/helpers/send-request'\nimport { validatePathParameters } from '@/v2/blocks/operation-block/helpers/validate-path-parameters'\nimport { generateClientOptions } from '@/v2/blocks/operation-code-sample'\nimport { RequestBlock } from '@/v2/blocks/request-block'\nimport { ResponseBlock } from '@/v2/blocks/response-block'\nimport { type History } from '@/v2/blocks/scalar-address-bar-block'\nimport type { ModalProps } from '@/v2/features/modal/Modal.vue'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nimport Header from './components/Header.vue'\n\nconst {\n authMeta,\n environment,\n eventBus,\n exampleKey,\n document,\n workspaceCookies = [],\n documentCookies = [],\n hideClientButton,\n httpClients = AVAILABLE_CLIENTS,\n history = [],\n method,\n operation,\n path,\n plugins = [],\n proxyUrl,\n requestBodyCompositionSelection,\n securitySchemes,\n selectedClient,\n server,\n environments,\n options,\n activeEnvironment,\n serverMeta,\n selectedSecurity,\n selectedSecuritySchemes,\n securityRequirements,\n defaultHeaders,\n} = defineProps<OperationBlockProps>()\n\n/** Hoist up client generation so it doesn't get re-generated on every operation */\nconst clientOptions = computed(() => generateClientOptions(httpClients))\n\nconst { toast } = useToasts()\n\n// Refs\nconst abortController = ref<AbortController | null>(null)\nconst response = ref<ResponseInstance | null>(null)\nconst requestPayload = ref<RequestPayload | null>(null)\n\n/** Cancel the request */\nconst cancelRequest = () => abortController.value?.abort(ERRORS.REQUEST_ABORTED)\n\n/** Execute the current operation example */\nconst handleExecute = async () => {\n const pathValidation = validatePathParameters(\n operation.parameters ?? [],\n exampleKey,\n )\n if (pathValidation.ok === false) {\n toast('Path parameters must have values.', 'error')\n return\n }\n\n const globalCookies = [...workspaceCookies, ...documentCookies]\n\n const { request: requestBuilder } = requestFactory({\n defaultHeaders,\n environment,\n exampleName: exampleKey,\n globalCookies,\n method,\n operation,\n path,\n proxyUrl,\n server,\n selectedSecuritySchemes,\n isElectron: isElectron(),\n requestBodyCompositionSelection,\n })\n\n // Stop any previous streaming response\n if (response.value && 'reader' in response.value) {\n response.value.reader.cancel()\n }\n\n const variablesStore = createVariablesStoreForRequest()\n\n // Execute the beforeRequest hook (plugins receive RequestFactory, not fetch Request)\n await executeHook(\n {\n requestBuilder,\n document,\n operation,\n variablesStore,\n },\n 'beforeRequest',\n plugins,\n )\n\n const envVariables = {\n ...getEnvironmentVariables(environment),\n ...variablesStore.getVariables(),\n }\n\n // Build the fetch Request after hooks may have mutated the factory\n const requestResult = (() => {\n try {\n return {\n ok: true,\n result: buildRequest(requestBuilder, {\n envVariables,\n }),\n } as const\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n ok: false,\n error: message,\n } as const\n }\n })()\n\n if (requestResult.ok === false) {\n toast(requestResult.error, 'error')\n return\n }\n\n // Store the abort controller for cancellation\n abortController.value = requestResult.result.controller\n\n // Execute the hooks\n eventBus.emit('hooks:on:request:sent', {\n meta: {\n method,\n path,\n exampleKey,\n },\n })\n\n /** Execute the request */\n const [sendError, sendResult] = await sendRequest({\n isUsingProxy: requestResult.result.isUsingProxy,\n requestPayload: requestResult.result.requestPayload,\n plugins,\n })\n\n if (sendResult) {\n // Execute the responseReceived hook\n await executeHook(\n {\n response: sendResult.originalResponse.clone(),\n requestBuilder,\n request: buildSafeBodyRequest(...sendResult.requestPayload),\n document,\n operation,\n variablesStore,\n },\n 'responseReceived',\n plugins,\n )\n }\n\n // Execute the hooks\n eventBus.emit('hooks:on:request:complete', {\n payload: sendResult\n ? {\n response: sendResult.originalResponse.clone(),\n requestPayload: sendResult.requestPayload,\n duration: sendResult.response.duration,\n timestamp: sendResult.timestamp,\n }\n : undefined,\n meta: {\n method,\n path,\n exampleKey,\n },\n })\n\n if (sendError) {\n // clean up the response and request\n response.value = null\n requestPayload.value = null\n abortController.value = null\n\n toast(sendError.message, 'error')\n return\n }\n\n // Store the response\n response.value = sendResult.response\n requestPayload.value = sendResult.requestPayload\n\n // Cache non-streaming responses so they can be restored when navigating back\n if (!isStreamingResponse(sendResult.response)) {\n responseCache.set(getOperationExampleKey(method, path, exampleKey), {\n response: sendResult.response,\n requestPayload: sendResult.requestPayload,\n })\n }\n}\n\nonMounted(() => {\n eventBus.on('operation:send:request:hotkey', handleExecute)\n eventBus.on('operation:cancel:request', cancelRequest)\n})\nonBeforeUnmount(() => {\n eventBus.off('operation:send:request:hotkey', handleExecute)\n eventBus.off('operation:cancel:request', cancelRequest)\n})\n\nconst operationHistory = computed<History[]>(() =>\n history\n .map((entry) => ({\n method: entry.request.method as HttpMethodType,\n path: entry.request.url,\n duration: entry.time,\n status: entry.response.status,\n }))\n .reverse(),\n)\n\nconst handleSelectHistoryItem = ({ index }: { index: number }) => {\n const transformedIndex = (history.length ?? 0) - index - 1\n const historyItem = history[transformedIndex]\n if (!historyItem) {\n return\n }\n\n const navigate = () =>\n eventBus.emit('ui:navigate', {\n page: 'example',\n method,\n path,\n exampleName: 'draft',\n callback: (status) => {\n // Do not replace the response if the navigation was not successful\n if (status !== 'success') {\n return\n }\n // Reconstruct the response\n const fetchResponse = harToFetchResponse({\n harResponse: historyItem.response,\n url: historyItem.request.url,\n method,\n path,\n duration: historyItem.time,\n })\n\n // Reconstruct the request\n const fetchRequest = harToFetchRequest({\n harRequest: historyItem.request,\n })\n\n // Update the response and request\n response.value = fetchResponse\n requestPayload.value = fetchRequest\n },\n })\n\n eventBus.emit('operation:reload:history', {\n meta: {\n path,\n method,\n },\n index: transformedIndex,\n callback: navigate,\n })\n}\n\n/**\n * When the path, method, or example key changes: save current response to\n * cache (so it can be restored when navigating back), then restore from cache\n * for the new operation or clear if no cached response. Response is only\n * cleared on page refresh or when making a new request for that operation.\n */\nwatch(\n [() => path, () => method, () => exampleKey],\n ([newPath, newMethod, newExampleKey]) => {\n const newKey = getOperationExampleKey(newMethod, newPath, newExampleKey)\n const cached = responseCache.get(newKey)\n if (cached) {\n response.value = cached.response\n requestPayload.value = cached.requestPayload\n } else {\n response.value = null\n requestPayload.value = null\n }\n\n // Cancel any in-flight request\n cancelRequest()\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n // We cancel the request if the component is unmounted\n cancelRequest()\n})\n</script>\n<template>\n <div class=\"bg-b-1 flex h-full flex-col\">\n <div\n class=\"lg:min-h-header flex w-full flex-wrap items-center justify-center p-2 lg:p-0\">\n <!-- Address Bar -->\n <Header\n :activeEnvironment\n :documentUrl\n :environment\n :environments\n :eventBus\n :hideClientButton\n :history=\"operationHistory\"\n :integration\n :layout\n :method\n :path\n :server\n :serverMeta\n :servers\n :source\n @execute=\"handleExecute\"\n @select:history:item=\"handleSelectHistoryItem\" />\n </div>\n\n <ViewLayout class=\"border-t\">\n <ViewLayoutContent class=\"flex-1\">\n <!-- Request Section -->\n <RequestBlock\n :authMeta\n :clientOptions\n :defaultHeaders\n :documentCookies\n :environment\n :eventBus\n :exampleKey\n :layout\n :method\n :operation\n :options=\"toValue(options)\"\n :path\n :plugins\n :proxyUrl\n :requestBodyCompositionSelection\n :securityRequirements\n :securitySchemes\n :selectedClient\n :selectedSecurity\n :selectedSecuritySchemes\n :server\n :workspaceCookies />\n\n <!-- Response Section -->\n <ResponseBlock\n :appVersion\n :eventBus\n :layout\n :plugins\n :requestPayload\n :response\n :totalPerformedRequests=\"operationHistory.length\" />\n </ViewLayoutContent>\n </ViewLayout>\n </div>\n</template>\n"],"mappings":""}
{"version":3,"file":"OperationBlock.vue.js","names":[],"sources":["../../../../src/v2/blocks/operation-block/OperationBlock.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * OperationBlock\n *\n * Orchestrates the operation view by wiring together the Header, OperationBlock,\n * and ResponseBlock. Forwards user interactions to the workspace event bus and\n * passes through configuration such as auth, servers, plugins, and environment.\n * This component keeps the Operation page lean by centralizing event emission\n * and prop wiring between the blocks.\n *\n * Notable behavior:\n * - Uses operation['x-scalar-method'] and operation['x-scalar-path'] to provide\n * draft overrides for the UI when present.\n */\nexport default {\n name: 'OperationBlock',\n}\n\nexport type OperationBlockProps = {\n /** Event bus */\n eventBus: WorkspaceEventBus\n /** Application version */\n appVersion: string\n /** Openapi document */\n document: OpenApiDocument\n /** Workspace cookies */\n workspaceCookies: XScalarCookie[]\n /** Document cookies */\n documentCookies: XScalarCookie[]\n /** Current request path */\n path: string\n /** Current request method */\n method: HttpMethodType\n /** HTTP clients */\n httpClients: AvailableClients\n /** The history for the operation */\n history?: HistoryEntry[]\n /** Client layout */\n layout: ClientLayout\n /** Currently selected server */\n server: ServerObject | null\n /** Currently selected client */\n selectedClient: WorkspaceStore['workspace']['x-scalar-default-client']\n /** Server list available for operation/document */\n servers: ServerObject[]\n /** Meta information for the server */\n serverMeta: ServerMeta\n /** Hides the client button on the header */\n hideClientButton?: boolean\n /** Client integration */\n integration?: string | null\n /** Openapi document url for `modal` mode to open the client app */\n documentUrl?: string\n /** Client source */\n source?: 'gitbook' | 'api-reference'\n /** Operation object */\n operation: OperationObject\n /** Currently selected example key for the current operation */\n exampleKey: string\n /** Meta information for the auth update */\n authMeta: AuthMeta\n /** Document defined security schemes */\n securitySchemes: MergedSecuritySchemes\n /** Client plugins */\n plugins: ClientPlugin[]\n /** Environment list */\n environments?: string[]\n /** Currently selected environment */\n activeEnvironment?: string\n /** For environment variables in the inputs */\n environment: XScalarEnvironment\n /** The proxy URL for sending requests */\n proxyUrl: string\n /** Currently selected security */\n selectedSecurity: SelectedSecurity\n /** Currently selected security schemes */\n selectedSecuritySchemes: SecuritySchemeObjectSecret[]\n /** Security requirements */\n securityRequirements: OpenApiDocument['security']\n /** Default headers */\n defaultHeaders: Record<string, string>\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection?: Record<string, number>\n /** Subset of config options for the modal */\n options?: ModalProps['options']\n}\n</script>\n<script setup lang=\"ts\">\nimport { ERRORS } from '@scalar/helpers/errors/normalize-error'\nimport { isElectron } from '@scalar/helpers/general/is-electron'\nimport { buildSafeBodyRequest } from '@scalar/helpers/http/can-method-have-body'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { executeHook, type ClientPlugin } from '@scalar/oas-utils/helpers'\nimport {\n AVAILABLE_CLIENTS,\n type AvailableClients,\n} from '@scalar/types/snippetz'\nimport { useToasts } from '@scalar/use-toasts'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { SelectedSecurity } from '@scalar/workspace-store/entities/auth'\nimport type { HistoryEntry } from '@scalar/workspace-store/entities/history/schema'\nimport type {\n AuthMeta,\n ServerMeta,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport {\n buildRequest,\n createVariablesStoreForRequest,\n getEnvironmentVariables,\n requestFactory,\n type MergedSecuritySchemes,\n type RequestPayload,\n type SecuritySchemeObjectSecret,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type {\n OpenApiDocument,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport type { OperationObject } from '@scalar/workspace-store/schemas/v3.1/strict/operation'\nimport { computed, onBeforeUnmount, onMounted, ref, toValue, watch } from 'vue'\n\nimport ViewLayout from '@/components/ViewLayout/ViewLayout.vue'\nimport ViewLayoutContent from '@/components/ViewLayout/ViewLayoutContent.vue'\nimport { harToFetchRequest } from '@/v2/blocks/operation-block/helpers/har-to-fetch-request'\nimport { harToFetchResponse } from '@/v2/blocks/operation-block/helpers/har-to-fetch-response'\nimport {\n getOperationExampleKey,\n isStreamingResponse,\n responseCache,\n} from '@/v2/blocks/operation-block/helpers/response-cache'\nimport {\n sendRequest,\n type ResponseInstance,\n} from '@/v2/blocks/operation-block/helpers/send-request'\nimport { validatePathParameters } from '@/v2/blocks/operation-block/helpers/validate-path-parameters'\nimport { generateClientOptions } from '@/v2/blocks/operation-code-sample'\nimport { RequestBlock } from '@/v2/blocks/request-block'\nimport { ResponseBlock } from '@/v2/blocks/response-block'\nimport { type History } from '@/v2/blocks/scalar-address-bar-block'\nimport type { ModalProps } from '@/v2/features/modal/Modal.vue'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nimport Header from './components/Header.vue'\n\nconst {\n authMeta,\n environment,\n eventBus,\n exampleKey,\n document,\n workspaceCookies = [],\n documentCookies = [],\n hideClientButton,\n httpClients = AVAILABLE_CLIENTS,\n history = [],\n method,\n operation,\n path,\n plugins = [],\n proxyUrl,\n requestBodyCompositionSelection,\n securitySchemes,\n selectedClient,\n server,\n environments,\n options,\n activeEnvironment,\n serverMeta,\n selectedSecurity,\n selectedSecuritySchemes,\n securityRequirements,\n defaultHeaders,\n} = defineProps<OperationBlockProps>()\n\n/** Hoist up client generation so it doesn't get re-generated on every operation */\nconst clientOptions = computed(() => generateClientOptions(httpClients))\n\nconst { toast } = useToasts()\n\n// Refs\nconst abortController = ref<AbortController | null>(null)\nconst response = ref<ResponseInstance | null>(null)\nconst requestPayload = ref<RequestPayload | null>(null)\n\n/** Cancel the request */\nconst cancelRequest = () => abortController.value?.abort(ERRORS.REQUEST_ABORTED)\n\n/** Execute the current operation example */\nconst handleExecute = async () => {\n const pathValidation = validatePathParameters(\n operation.parameters ?? [],\n exampleKey,\n )\n if (pathValidation.ok === false) {\n toast('Path parameters must have values.', 'error')\n return\n }\n\n const globalCookies = [...workspaceCookies, ...documentCookies]\n\n const { request: requestBuilder } = requestFactory({\n defaultHeaders,\n environment,\n exampleName: exampleKey,\n globalCookies,\n method,\n operation,\n path,\n proxyUrl,\n server,\n selectedSecuritySchemes,\n isElectron: isElectron(),\n requestBodyCompositionSelection,\n })\n\n // Stop any previous streaming response\n if (response.value && 'reader' in response.value) {\n response.value.reader.cancel()\n }\n\n const variablesStore = createVariablesStoreForRequest()\n\n // Execute the beforeRequest hook (plugins receive RequestFactory, not fetch Request)\n await executeHook(\n {\n requestBuilder,\n document,\n operation,\n variablesStore,\n },\n 'beforeRequest',\n plugins,\n )\n\n const envVariables = {\n ...getEnvironmentVariables(environment),\n ...variablesStore.getVariables(),\n }\n\n // Build the fetch Request after hooks may have mutated the factory\n const requestResult = (() => {\n try {\n return {\n ok: true,\n result: buildRequest(requestBuilder, {\n envVariables,\n }),\n } as const\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n ok: false,\n error: message,\n } as const\n }\n })()\n\n if (requestResult.ok === false) {\n toast(requestResult.error, 'error')\n return\n }\n\n // Store the abort controller for cancellation\n abortController.value = requestResult.result.controller\n\n // Execute the hooks\n eventBus.emit('hooks:on:request:sent', {\n meta: {\n method,\n path,\n exampleKey,\n },\n })\n\n /** Execute the request */\n const [sendError, sendResult] = await sendRequest({\n isUsingProxy: requestResult.result.isUsingProxy,\n requestPayload: requestResult.result.requestPayload,\n plugins,\n customFetch: toValue(options)?.customFetch,\n })\n\n if (sendResult) {\n // Execute the responseReceived hook\n await executeHook(\n {\n response: sendResult.originalResponse.clone(),\n requestBuilder,\n request: buildSafeBodyRequest(...sendResult.requestPayload),\n document,\n operation,\n variablesStore,\n },\n 'responseReceived',\n plugins,\n )\n }\n\n // Execute the hooks\n eventBus.emit('hooks:on:request:complete', {\n payload: sendResult\n ? {\n response: sendResult.originalResponse.clone(),\n requestPayload: sendResult.requestPayload,\n duration: sendResult.response.duration,\n timestamp: sendResult.timestamp,\n }\n : undefined,\n meta: {\n method,\n path,\n exampleKey,\n },\n })\n\n if (sendError) {\n // clean up the response and request\n response.value = null\n requestPayload.value = null\n abortController.value = null\n\n toast(sendError.message, 'error')\n return\n }\n\n // Store the response\n response.value = sendResult.response\n requestPayload.value = sendResult.requestPayload\n\n // Cache non-streaming responses so they can be restored when navigating back\n if (!isStreamingResponse(sendResult.response)) {\n responseCache.set(getOperationExampleKey(method, path, exampleKey), {\n response: sendResult.response,\n requestPayload: sendResult.requestPayload,\n })\n }\n}\n\nonMounted(() => {\n eventBus.on('operation:send:request:hotkey', handleExecute)\n eventBus.on('operation:cancel:request', cancelRequest)\n})\nonBeforeUnmount(() => {\n eventBus.off('operation:send:request:hotkey', handleExecute)\n eventBus.off('operation:cancel:request', cancelRequest)\n})\n\nconst operationHistory = computed<History[]>(() =>\n history\n .map((entry) => ({\n method: entry.request.method as HttpMethodType,\n path: entry.request.url,\n duration: entry.time,\n status: entry.response.status,\n }))\n .reverse(),\n)\n\nconst handleSelectHistoryItem = ({ index }: { index: number }) => {\n const transformedIndex = (history.length ?? 0) - index - 1\n const historyItem = history[transformedIndex]\n if (!historyItem) {\n return\n }\n\n const navigate = () =>\n eventBus.emit('ui:navigate', {\n page: 'example',\n method,\n path,\n exampleName: 'draft',\n callback: (status) => {\n // Do not replace the response if the navigation was not successful\n if (status !== 'success') {\n return\n }\n // Reconstruct the response\n const fetchResponse = harToFetchResponse({\n harResponse: historyItem.response,\n url: historyItem.request.url,\n method,\n path,\n duration: historyItem.time,\n })\n\n // Reconstruct the request\n const fetchRequest = harToFetchRequest({\n harRequest: historyItem.request,\n })\n\n // Update the response and request\n response.value = fetchResponse\n requestPayload.value = fetchRequest\n },\n })\n\n eventBus.emit('operation:reload:history', {\n meta: {\n path,\n method,\n },\n index: transformedIndex,\n callback: navigate,\n })\n}\n\n/**\n * When the path, method, or example key changes: save current response to\n * cache (so it can be restored when navigating back), then restore from cache\n * for the new operation or clear if no cached response. Response is only\n * cleared on page refresh or when making a new request for that operation.\n */\nwatch(\n [() => path, () => method, () => exampleKey],\n ([newPath, newMethod, newExampleKey]) => {\n const newKey = getOperationExampleKey(newMethod, newPath, newExampleKey)\n const cached = responseCache.get(newKey)\n if (cached) {\n response.value = cached.response\n requestPayload.value = cached.requestPayload\n } else {\n response.value = null\n requestPayload.value = null\n }\n\n // Cancel any in-flight request\n cancelRequest()\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n // We cancel the request if the component is unmounted\n cancelRequest()\n})\n</script>\n<template>\n <div class=\"bg-b-1 flex h-full flex-col\">\n <div\n class=\"lg:min-h-header flex w-full flex-wrap items-center justify-center p-2 lg:p-0\">\n <!-- Address Bar -->\n <Header\n :activeEnvironment\n :documentUrl\n :environment\n :environments\n :eventBus\n :hideClientButton\n :history=\"operationHistory\"\n :integration\n :layout\n :method\n :path\n :server\n :serverMeta\n :servers\n :source\n @execute=\"handleExecute\"\n @select:history:item=\"handleSelectHistoryItem\" />\n </div>\n\n <ViewLayout class=\"border-t\">\n <ViewLayoutContent class=\"flex-1\">\n <!-- Request Section -->\n <RequestBlock\n :authMeta\n :clientOptions\n :defaultHeaders\n :documentCookies\n :environment\n :eventBus\n :exampleKey\n :layout\n :method\n :operation\n :options=\"toValue(options)\"\n :path\n :plugins\n :proxyUrl\n :requestBodyCompositionSelection\n :securityRequirements\n :securitySchemes\n :selectedClient\n :selectedSecurity\n :selectedSecuritySchemes\n :server\n :workspaceCookies />\n\n <!-- Response Section -->\n <ResponseBlock\n :appVersion\n :eventBus\n :layout\n :plugins\n :requestPayload\n :response\n :totalPerformedRequests=\"operationHistory.length\" />\n </ViewLayoutContent>\n </ViewLayout>\n </div>\n</template>\n"],"mappings":""}

@@ -129,3 +129,4 @@ import ViewLayout_default from "../../../components/ViewLayout/ViewLayout.vue.js";

requestPayload: requestResult.result.requestPayload,
plugins: __props.plugins
plugins: __props.plugins,
customFetch: toValue(__props.options)?.customFetch
});

@@ -132,0 +133,0 @@ if (sendResult) await executeHook({

@@ -1,1 +0,1 @@

{"version":3,"file":"OperationBlock.vue.script.js","names":[],"sources":["../../../../src/v2/blocks/operation-block/OperationBlock.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * OperationBlock\n *\n * Orchestrates the operation view by wiring together the Header, OperationBlock,\n * and ResponseBlock. Forwards user interactions to the workspace event bus and\n * passes through configuration such as auth, servers, plugins, and environment.\n * This component keeps the Operation page lean by centralizing event emission\n * and prop wiring between the blocks.\n *\n * Notable behavior:\n * - Uses operation['x-scalar-method'] and operation['x-scalar-path'] to provide\n * draft overrides for the UI when present.\n */\nexport default {\n name: 'OperationBlock',\n}\n\nexport type OperationBlockProps = {\n /** Event bus */\n eventBus: WorkspaceEventBus\n /** Application version */\n appVersion: string\n /** Openapi document */\n document: OpenApiDocument\n /** Workspace cookies */\n workspaceCookies: XScalarCookie[]\n /** Document cookies */\n documentCookies: XScalarCookie[]\n /** Current request path */\n path: string\n /** Current request method */\n method: HttpMethodType\n /** HTTP clients */\n httpClients: AvailableClients\n /** The history for the operation */\n history?: HistoryEntry[]\n /** Client layout */\n layout: ClientLayout\n /** Currently selected server */\n server: ServerObject | null\n /** Currently selected client */\n selectedClient: WorkspaceStore['workspace']['x-scalar-default-client']\n /** Server list available for operation/document */\n servers: ServerObject[]\n /** Meta information for the server */\n serverMeta: ServerMeta\n /** Hides the client button on the header */\n hideClientButton?: boolean\n /** Client integration */\n integration?: string | null\n /** Openapi document url for `modal` mode to open the client app */\n documentUrl?: string\n /** Client source */\n source?: 'gitbook' | 'api-reference'\n /** Operation object */\n operation: OperationObject\n /** Currently selected example key for the current operation */\n exampleKey: string\n /** Meta information for the auth update */\n authMeta: AuthMeta\n /** Document defined security schemes */\n securitySchemes: MergedSecuritySchemes\n /** Client plugins */\n plugins: ClientPlugin[]\n /** Environment list */\n environments?: string[]\n /** Currently selected environment */\n activeEnvironment?: string\n /** For environment variables in the inputs */\n environment: XScalarEnvironment\n /** The proxy URL for sending requests */\n proxyUrl: string\n /** Currently selected security */\n selectedSecurity: SelectedSecurity\n /** Currently selected security schemes */\n selectedSecuritySchemes: SecuritySchemeObjectSecret[]\n /** Security requirements */\n securityRequirements: OpenApiDocument['security']\n /** Default headers */\n defaultHeaders: Record<string, string>\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection?: Record<string, number>\n /** Subset of config options for the modal */\n options?: ModalProps['options']\n}\n</script>\n<script setup lang=\"ts\">\nimport { ERRORS } from '@scalar/helpers/errors/normalize-error'\nimport { isElectron } from '@scalar/helpers/general/is-electron'\nimport { buildSafeBodyRequest } from '@scalar/helpers/http/can-method-have-body'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { executeHook, type ClientPlugin } from '@scalar/oas-utils/helpers'\nimport {\n AVAILABLE_CLIENTS,\n type AvailableClients,\n} from '@scalar/types/snippetz'\nimport { useToasts } from '@scalar/use-toasts'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { SelectedSecurity } from '@scalar/workspace-store/entities/auth'\nimport type { HistoryEntry } from '@scalar/workspace-store/entities/history/schema'\nimport type {\n AuthMeta,\n ServerMeta,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport {\n buildRequest,\n createVariablesStoreForRequest,\n getEnvironmentVariables,\n requestFactory,\n type MergedSecuritySchemes,\n type RequestPayload,\n type SecuritySchemeObjectSecret,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type {\n OpenApiDocument,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport type { OperationObject } from '@scalar/workspace-store/schemas/v3.1/strict/operation'\nimport { computed, onBeforeUnmount, onMounted, ref, toValue, watch } from 'vue'\n\nimport ViewLayout from '@/components/ViewLayout/ViewLayout.vue'\nimport ViewLayoutContent from '@/components/ViewLayout/ViewLayoutContent.vue'\nimport { harToFetchRequest } from '@/v2/blocks/operation-block/helpers/har-to-fetch-request'\nimport { harToFetchResponse } from '@/v2/blocks/operation-block/helpers/har-to-fetch-response'\nimport {\n getOperationExampleKey,\n isStreamingResponse,\n responseCache,\n} from '@/v2/blocks/operation-block/helpers/response-cache'\nimport {\n sendRequest,\n type ResponseInstance,\n} from '@/v2/blocks/operation-block/helpers/send-request'\nimport { validatePathParameters } from '@/v2/blocks/operation-block/helpers/validate-path-parameters'\nimport { generateClientOptions } from '@/v2/blocks/operation-code-sample'\nimport { RequestBlock } from '@/v2/blocks/request-block'\nimport { ResponseBlock } from '@/v2/blocks/response-block'\nimport { type History } from '@/v2/blocks/scalar-address-bar-block'\nimport type { ModalProps } from '@/v2/features/modal/Modal.vue'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nimport Header from './components/Header.vue'\n\nconst {\n authMeta,\n environment,\n eventBus,\n exampleKey,\n document,\n workspaceCookies = [],\n documentCookies = [],\n hideClientButton,\n httpClients = AVAILABLE_CLIENTS,\n history = [],\n method,\n operation,\n path,\n plugins = [],\n proxyUrl,\n requestBodyCompositionSelection,\n securitySchemes,\n selectedClient,\n server,\n environments,\n options,\n activeEnvironment,\n serverMeta,\n selectedSecurity,\n selectedSecuritySchemes,\n securityRequirements,\n defaultHeaders,\n} = defineProps<OperationBlockProps>()\n\n/** Hoist up client generation so it doesn't get re-generated on every operation */\nconst clientOptions = computed(() => generateClientOptions(httpClients))\n\nconst { toast } = useToasts()\n\n// Refs\nconst abortController = ref<AbortController | null>(null)\nconst response = ref<ResponseInstance | null>(null)\nconst requestPayload = ref<RequestPayload | null>(null)\n\n/** Cancel the request */\nconst cancelRequest = () => abortController.value?.abort(ERRORS.REQUEST_ABORTED)\n\n/** Execute the current operation example */\nconst handleExecute = async () => {\n const pathValidation = validatePathParameters(\n operation.parameters ?? [],\n exampleKey,\n )\n if (pathValidation.ok === false) {\n toast('Path parameters must have values.', 'error')\n return\n }\n\n const globalCookies = [...workspaceCookies, ...documentCookies]\n\n const { request: requestBuilder } = requestFactory({\n defaultHeaders,\n environment,\n exampleName: exampleKey,\n globalCookies,\n method,\n operation,\n path,\n proxyUrl,\n server,\n selectedSecuritySchemes,\n isElectron: isElectron(),\n requestBodyCompositionSelection,\n })\n\n // Stop any previous streaming response\n if (response.value && 'reader' in response.value) {\n response.value.reader.cancel()\n }\n\n const variablesStore = createVariablesStoreForRequest()\n\n // Execute the beforeRequest hook (plugins receive RequestFactory, not fetch Request)\n await executeHook(\n {\n requestBuilder,\n document,\n operation,\n variablesStore,\n },\n 'beforeRequest',\n plugins,\n )\n\n const envVariables = {\n ...getEnvironmentVariables(environment),\n ...variablesStore.getVariables(),\n }\n\n // Build the fetch Request after hooks may have mutated the factory\n const requestResult = (() => {\n try {\n return {\n ok: true,\n result: buildRequest(requestBuilder, {\n envVariables,\n }),\n } as const\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n ok: false,\n error: message,\n } as const\n }\n })()\n\n if (requestResult.ok === false) {\n toast(requestResult.error, 'error')\n return\n }\n\n // Store the abort controller for cancellation\n abortController.value = requestResult.result.controller\n\n // Execute the hooks\n eventBus.emit('hooks:on:request:sent', {\n meta: {\n method,\n path,\n exampleKey,\n },\n })\n\n /** Execute the request */\n const [sendError, sendResult] = await sendRequest({\n isUsingProxy: requestResult.result.isUsingProxy,\n requestPayload: requestResult.result.requestPayload,\n plugins,\n })\n\n if (sendResult) {\n // Execute the responseReceived hook\n await executeHook(\n {\n response: sendResult.originalResponse.clone(),\n requestBuilder,\n request: buildSafeBodyRequest(...sendResult.requestPayload),\n document,\n operation,\n variablesStore,\n },\n 'responseReceived',\n plugins,\n )\n }\n\n // Execute the hooks\n eventBus.emit('hooks:on:request:complete', {\n payload: sendResult\n ? {\n response: sendResult.originalResponse.clone(),\n requestPayload: sendResult.requestPayload,\n duration: sendResult.response.duration,\n timestamp: sendResult.timestamp,\n }\n : undefined,\n meta: {\n method,\n path,\n exampleKey,\n },\n })\n\n if (sendError) {\n // clean up the response and request\n response.value = null\n requestPayload.value = null\n abortController.value = null\n\n toast(sendError.message, 'error')\n return\n }\n\n // Store the response\n response.value = sendResult.response\n requestPayload.value = sendResult.requestPayload\n\n // Cache non-streaming responses so they can be restored when navigating back\n if (!isStreamingResponse(sendResult.response)) {\n responseCache.set(getOperationExampleKey(method, path, exampleKey), {\n response: sendResult.response,\n requestPayload: sendResult.requestPayload,\n })\n }\n}\n\nonMounted(() => {\n eventBus.on('operation:send:request:hotkey', handleExecute)\n eventBus.on('operation:cancel:request', cancelRequest)\n})\nonBeforeUnmount(() => {\n eventBus.off('operation:send:request:hotkey', handleExecute)\n eventBus.off('operation:cancel:request', cancelRequest)\n})\n\nconst operationHistory = computed<History[]>(() =>\n history\n .map((entry) => ({\n method: entry.request.method as HttpMethodType,\n path: entry.request.url,\n duration: entry.time,\n status: entry.response.status,\n }))\n .reverse(),\n)\n\nconst handleSelectHistoryItem = ({ index }: { index: number }) => {\n const transformedIndex = (history.length ?? 0) - index - 1\n const historyItem = history[transformedIndex]\n if (!historyItem) {\n return\n }\n\n const navigate = () =>\n eventBus.emit('ui:navigate', {\n page: 'example',\n method,\n path,\n exampleName: 'draft',\n callback: (status) => {\n // Do not replace the response if the navigation was not successful\n if (status !== 'success') {\n return\n }\n // Reconstruct the response\n const fetchResponse = harToFetchResponse({\n harResponse: historyItem.response,\n url: historyItem.request.url,\n method,\n path,\n duration: historyItem.time,\n })\n\n // Reconstruct the request\n const fetchRequest = harToFetchRequest({\n harRequest: historyItem.request,\n })\n\n // Update the response and request\n response.value = fetchResponse\n requestPayload.value = fetchRequest\n },\n })\n\n eventBus.emit('operation:reload:history', {\n meta: {\n path,\n method,\n },\n index: transformedIndex,\n callback: navigate,\n })\n}\n\n/**\n * When the path, method, or example key changes: save current response to\n * cache (so it can be restored when navigating back), then restore from cache\n * for the new operation or clear if no cached response. Response is only\n * cleared on page refresh or when making a new request for that operation.\n */\nwatch(\n [() => path, () => method, () => exampleKey],\n ([newPath, newMethod, newExampleKey]) => {\n const newKey = getOperationExampleKey(newMethod, newPath, newExampleKey)\n const cached = responseCache.get(newKey)\n if (cached) {\n response.value = cached.response\n requestPayload.value = cached.requestPayload\n } else {\n response.value = null\n requestPayload.value = null\n }\n\n // Cancel any in-flight request\n cancelRequest()\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n // We cancel the request if the component is unmounted\n cancelRequest()\n})\n</script>\n<template>\n <div class=\"bg-b-1 flex h-full flex-col\">\n <div\n class=\"lg:min-h-header flex w-full flex-wrap items-center justify-center p-2 lg:p-0\">\n <!-- Address Bar -->\n <Header\n :activeEnvironment\n :documentUrl\n :environment\n :environments\n :eventBus\n :hideClientButton\n :history=\"operationHistory\"\n :integration\n :layout\n :method\n :path\n :server\n :serverMeta\n :servers\n :source\n @execute=\"handleExecute\"\n @select:history:item=\"handleSelectHistoryItem\" />\n </div>\n\n <ViewLayout class=\"border-t\">\n <ViewLayoutContent class=\"flex-1\">\n <!-- Request Section -->\n <RequestBlock\n :authMeta\n :clientOptions\n :defaultHeaders\n :documentCookies\n :environment\n :eventBus\n :exampleKey\n :layout\n :method\n :operation\n :options=\"toValue(options)\"\n :path\n :plugins\n :proxyUrl\n :requestBodyCompositionSelection\n :securityRequirements\n :securitySchemes\n :selectedClient\n :selectedSecurity\n :selectedSecuritySchemes\n :server\n :workspaceCookies />\n\n <!-- Response Section -->\n <ResponseBlock\n :appVersion\n :eventBus\n :layout\n :plugins\n :requestPayload\n :response\n :totalPerformedRequests=\"operationHistory.length\" />\n </ViewLayoutContent>\n </ViewLayout>\n </div>\n</template>\n"],"mappings":"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"}
{"version":3,"file":"OperationBlock.vue.script.js","names":[],"sources":["../../../../src/v2/blocks/operation-block/OperationBlock.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * OperationBlock\n *\n * Orchestrates the operation view by wiring together the Header, OperationBlock,\n * and ResponseBlock. Forwards user interactions to the workspace event bus and\n * passes through configuration such as auth, servers, plugins, and environment.\n * This component keeps the Operation page lean by centralizing event emission\n * and prop wiring between the blocks.\n *\n * Notable behavior:\n * - Uses operation['x-scalar-method'] and operation['x-scalar-path'] to provide\n * draft overrides for the UI when present.\n */\nexport default {\n name: 'OperationBlock',\n}\n\nexport type OperationBlockProps = {\n /** Event bus */\n eventBus: WorkspaceEventBus\n /** Application version */\n appVersion: string\n /** Openapi document */\n document: OpenApiDocument\n /** Workspace cookies */\n workspaceCookies: XScalarCookie[]\n /** Document cookies */\n documentCookies: XScalarCookie[]\n /** Current request path */\n path: string\n /** Current request method */\n method: HttpMethodType\n /** HTTP clients */\n httpClients: AvailableClients\n /** The history for the operation */\n history?: HistoryEntry[]\n /** Client layout */\n layout: ClientLayout\n /** Currently selected server */\n server: ServerObject | null\n /** Currently selected client */\n selectedClient: WorkspaceStore['workspace']['x-scalar-default-client']\n /** Server list available for operation/document */\n servers: ServerObject[]\n /** Meta information for the server */\n serverMeta: ServerMeta\n /** Hides the client button on the header */\n hideClientButton?: boolean\n /** Client integration */\n integration?: string | null\n /** Openapi document url for `modal` mode to open the client app */\n documentUrl?: string\n /** Client source */\n source?: 'gitbook' | 'api-reference'\n /** Operation object */\n operation: OperationObject\n /** Currently selected example key for the current operation */\n exampleKey: string\n /** Meta information for the auth update */\n authMeta: AuthMeta\n /** Document defined security schemes */\n securitySchemes: MergedSecuritySchemes\n /** Client plugins */\n plugins: ClientPlugin[]\n /** Environment list */\n environments?: string[]\n /** Currently selected environment */\n activeEnvironment?: string\n /** For environment variables in the inputs */\n environment: XScalarEnvironment\n /** The proxy URL for sending requests */\n proxyUrl: string\n /** Currently selected security */\n selectedSecurity: SelectedSecurity\n /** Currently selected security schemes */\n selectedSecuritySchemes: SecuritySchemeObjectSecret[]\n /** Security requirements */\n securityRequirements: OpenApiDocument['security']\n /** Default headers */\n defaultHeaders: Record<string, string>\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection?: Record<string, number>\n /** Subset of config options for the modal */\n options?: ModalProps['options']\n}\n</script>\n<script setup lang=\"ts\">\nimport { ERRORS } from '@scalar/helpers/errors/normalize-error'\nimport { isElectron } from '@scalar/helpers/general/is-electron'\nimport { buildSafeBodyRequest } from '@scalar/helpers/http/can-method-have-body'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { executeHook, type ClientPlugin } from '@scalar/oas-utils/helpers'\nimport {\n AVAILABLE_CLIENTS,\n type AvailableClients,\n} from '@scalar/types/snippetz'\nimport { useToasts } from '@scalar/use-toasts'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { SelectedSecurity } from '@scalar/workspace-store/entities/auth'\nimport type { HistoryEntry } from '@scalar/workspace-store/entities/history/schema'\nimport type {\n AuthMeta,\n ServerMeta,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport {\n buildRequest,\n createVariablesStoreForRequest,\n getEnvironmentVariables,\n requestFactory,\n type MergedSecuritySchemes,\n type RequestPayload,\n type SecuritySchemeObjectSecret,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type {\n OpenApiDocument,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport type { OperationObject } from '@scalar/workspace-store/schemas/v3.1/strict/operation'\nimport { computed, onBeforeUnmount, onMounted, ref, toValue, watch } from 'vue'\n\nimport ViewLayout from '@/components/ViewLayout/ViewLayout.vue'\nimport ViewLayoutContent from '@/components/ViewLayout/ViewLayoutContent.vue'\nimport { harToFetchRequest } from '@/v2/blocks/operation-block/helpers/har-to-fetch-request'\nimport { harToFetchResponse } from '@/v2/blocks/operation-block/helpers/har-to-fetch-response'\nimport {\n getOperationExampleKey,\n isStreamingResponse,\n responseCache,\n} from '@/v2/blocks/operation-block/helpers/response-cache'\nimport {\n sendRequest,\n type ResponseInstance,\n} from '@/v2/blocks/operation-block/helpers/send-request'\nimport { validatePathParameters } from '@/v2/blocks/operation-block/helpers/validate-path-parameters'\nimport { generateClientOptions } from '@/v2/blocks/operation-code-sample'\nimport { RequestBlock } from '@/v2/blocks/request-block'\nimport { ResponseBlock } from '@/v2/blocks/response-block'\nimport { type History } from '@/v2/blocks/scalar-address-bar-block'\nimport type { ModalProps } from '@/v2/features/modal/Modal.vue'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nimport Header from './components/Header.vue'\n\nconst {\n authMeta,\n environment,\n eventBus,\n exampleKey,\n document,\n workspaceCookies = [],\n documentCookies = [],\n hideClientButton,\n httpClients = AVAILABLE_CLIENTS,\n history = [],\n method,\n operation,\n path,\n plugins = [],\n proxyUrl,\n requestBodyCompositionSelection,\n securitySchemes,\n selectedClient,\n server,\n environments,\n options,\n activeEnvironment,\n serverMeta,\n selectedSecurity,\n selectedSecuritySchemes,\n securityRequirements,\n defaultHeaders,\n} = defineProps<OperationBlockProps>()\n\n/** Hoist up client generation so it doesn't get re-generated on every operation */\nconst clientOptions = computed(() => generateClientOptions(httpClients))\n\nconst { toast } = useToasts()\n\n// Refs\nconst abortController = ref<AbortController | null>(null)\nconst response = ref<ResponseInstance | null>(null)\nconst requestPayload = ref<RequestPayload | null>(null)\n\n/** Cancel the request */\nconst cancelRequest = () => abortController.value?.abort(ERRORS.REQUEST_ABORTED)\n\n/** Execute the current operation example */\nconst handleExecute = async () => {\n const pathValidation = validatePathParameters(\n operation.parameters ?? [],\n exampleKey,\n )\n if (pathValidation.ok === false) {\n toast('Path parameters must have values.', 'error')\n return\n }\n\n const globalCookies = [...workspaceCookies, ...documentCookies]\n\n const { request: requestBuilder } = requestFactory({\n defaultHeaders,\n environment,\n exampleName: exampleKey,\n globalCookies,\n method,\n operation,\n path,\n proxyUrl,\n server,\n selectedSecuritySchemes,\n isElectron: isElectron(),\n requestBodyCompositionSelection,\n })\n\n // Stop any previous streaming response\n if (response.value && 'reader' in response.value) {\n response.value.reader.cancel()\n }\n\n const variablesStore = createVariablesStoreForRequest()\n\n // Execute the beforeRequest hook (plugins receive RequestFactory, not fetch Request)\n await executeHook(\n {\n requestBuilder,\n document,\n operation,\n variablesStore,\n },\n 'beforeRequest',\n plugins,\n )\n\n const envVariables = {\n ...getEnvironmentVariables(environment),\n ...variablesStore.getVariables(),\n }\n\n // Build the fetch Request after hooks may have mutated the factory\n const requestResult = (() => {\n try {\n return {\n ok: true,\n result: buildRequest(requestBuilder, {\n envVariables,\n }),\n } as const\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n ok: false,\n error: message,\n } as const\n }\n })()\n\n if (requestResult.ok === false) {\n toast(requestResult.error, 'error')\n return\n }\n\n // Store the abort controller for cancellation\n abortController.value = requestResult.result.controller\n\n // Execute the hooks\n eventBus.emit('hooks:on:request:sent', {\n meta: {\n method,\n path,\n exampleKey,\n },\n })\n\n /** Execute the request */\n const [sendError, sendResult] = await sendRequest({\n isUsingProxy: requestResult.result.isUsingProxy,\n requestPayload: requestResult.result.requestPayload,\n plugins,\n customFetch: toValue(options)?.customFetch,\n })\n\n if (sendResult) {\n // Execute the responseReceived hook\n await executeHook(\n {\n response: sendResult.originalResponse.clone(),\n requestBuilder,\n request: buildSafeBodyRequest(...sendResult.requestPayload),\n document,\n operation,\n variablesStore,\n },\n 'responseReceived',\n plugins,\n )\n }\n\n // Execute the hooks\n eventBus.emit('hooks:on:request:complete', {\n payload: sendResult\n ? {\n response: sendResult.originalResponse.clone(),\n requestPayload: sendResult.requestPayload,\n duration: sendResult.response.duration,\n timestamp: sendResult.timestamp,\n }\n : undefined,\n meta: {\n method,\n path,\n exampleKey,\n },\n })\n\n if (sendError) {\n // clean up the response and request\n response.value = null\n requestPayload.value = null\n abortController.value = null\n\n toast(sendError.message, 'error')\n return\n }\n\n // Store the response\n response.value = sendResult.response\n requestPayload.value = sendResult.requestPayload\n\n // Cache non-streaming responses so they can be restored when navigating back\n if (!isStreamingResponse(sendResult.response)) {\n responseCache.set(getOperationExampleKey(method, path, exampleKey), {\n response: sendResult.response,\n requestPayload: sendResult.requestPayload,\n })\n }\n}\n\nonMounted(() => {\n eventBus.on('operation:send:request:hotkey', handleExecute)\n eventBus.on('operation:cancel:request', cancelRequest)\n})\nonBeforeUnmount(() => {\n eventBus.off('operation:send:request:hotkey', handleExecute)\n eventBus.off('operation:cancel:request', cancelRequest)\n})\n\nconst operationHistory = computed<History[]>(() =>\n history\n .map((entry) => ({\n method: entry.request.method as HttpMethodType,\n path: entry.request.url,\n duration: entry.time,\n status: entry.response.status,\n }))\n .reverse(),\n)\n\nconst handleSelectHistoryItem = ({ index }: { index: number }) => {\n const transformedIndex = (history.length ?? 0) - index - 1\n const historyItem = history[transformedIndex]\n if (!historyItem) {\n return\n }\n\n const navigate = () =>\n eventBus.emit('ui:navigate', {\n page: 'example',\n method,\n path,\n exampleName: 'draft',\n callback: (status) => {\n // Do not replace the response if the navigation was not successful\n if (status !== 'success') {\n return\n }\n // Reconstruct the response\n const fetchResponse = harToFetchResponse({\n harResponse: historyItem.response,\n url: historyItem.request.url,\n method,\n path,\n duration: historyItem.time,\n })\n\n // Reconstruct the request\n const fetchRequest = harToFetchRequest({\n harRequest: historyItem.request,\n })\n\n // Update the response and request\n response.value = fetchResponse\n requestPayload.value = fetchRequest\n },\n })\n\n eventBus.emit('operation:reload:history', {\n meta: {\n path,\n method,\n },\n index: transformedIndex,\n callback: navigate,\n })\n}\n\n/**\n * When the path, method, or example key changes: save current response to\n * cache (so it can be restored when navigating back), then restore from cache\n * for the new operation or clear if no cached response. Response is only\n * cleared on page refresh or when making a new request for that operation.\n */\nwatch(\n [() => path, () => method, () => exampleKey],\n ([newPath, newMethod, newExampleKey]) => {\n const newKey = getOperationExampleKey(newMethod, newPath, newExampleKey)\n const cached = responseCache.get(newKey)\n if (cached) {\n response.value = cached.response\n requestPayload.value = cached.requestPayload\n } else {\n response.value = null\n requestPayload.value = null\n }\n\n // Cancel any in-flight request\n cancelRequest()\n },\n { immediate: true },\n)\n\nonBeforeUnmount(() => {\n // We cancel the request if the component is unmounted\n cancelRequest()\n})\n</script>\n<template>\n <div class=\"bg-b-1 flex h-full flex-col\">\n <div\n class=\"lg:min-h-header flex w-full flex-wrap items-center justify-center p-2 lg:p-0\">\n <!-- Address Bar -->\n <Header\n :activeEnvironment\n :documentUrl\n :environment\n :environments\n :eventBus\n :hideClientButton\n :history=\"operationHistory\"\n :integration\n :layout\n :method\n :path\n :server\n :serverMeta\n :servers\n :source\n @execute=\"handleExecute\"\n @select:history:item=\"handleSelectHistoryItem\" />\n </div>\n\n <ViewLayout class=\"border-t\">\n <ViewLayoutContent class=\"flex-1\">\n <!-- Request Section -->\n <RequestBlock\n :authMeta\n :clientOptions\n :defaultHeaders\n :documentCookies\n :environment\n :eventBus\n :exampleKey\n :layout\n :method\n :operation\n :options=\"toValue(options)\"\n :path\n :plugins\n :proxyUrl\n :requestBodyCompositionSelection\n :securityRequirements\n :securitySchemes\n :selectedClient\n :selectedSecurity\n :selectedSecuritySchemes\n :server\n :workspaceCookies />\n\n <!-- Response Section -->\n <ResponseBlock\n :appVersion\n :eventBus\n :layout\n :plugins\n :requestPayload\n :response\n :totalPerformedRequests=\"operationHistory.length\" />\n </ViewLayoutContent>\n </ViewLayout>\n </div>\n</template>\n"],"mappings":"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"}

@@ -1,1 +0,1 @@

{"version":3,"file":"OperationCodeSample.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/operation-code-sample/components/OperationCodeSample.vue"],"names":[],"mappings":"AAqeA,OAAO,KAAK,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,mCAAmC,CAAA;AAErF,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACxD,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAEvE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAA;AACzF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qEAAqE,CAAA;AACxG,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACb,MAAM,8DAA8D,CAAA;AAiBrE,OAAO,KAAK,EAEV,iBAAiB,EAElB,MAAM,yCAAyC,CAAA;AAMhD,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;OAGG;IACH,WAAW,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAA;IACpC;;OAEG;IACH,aAAa,EAAE,iBAAiB,EAAE,CAAA;IAClC;;;;OAIG;IACH,cAAc,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAA;IACzC;;OAEG;IACH,cAAc,CAAC,EAAE,YAAY,GAAG,IAAI,CAAA;IACpC;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;OAEG;IACH,QAAQ,EAAE,iBAAiB,CAAA;IAC3B;;OAEG;IACH,eAAe,EAAE,0BAA0B,EAAE,CAAA;IAC7C;;OAEG;IACH,MAAM,EAAE,cAAc,CAAA;IACtB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,SAAS,EAAE,eAAe,CAAA;IAC1B;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,MAAM,CAAA;IAC5B;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;OAEG;IACH,aAAa,CAAC,EAAE,aAAa,EAAE,CAAA;IAC/B;;;OAGG;IACH,+BAA+B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACzD,CAAA;AAED;;;;;;;;GAQG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;IAgLlB,8DAA8D;sBAC1C,MAAM;;;;IAD1B,8DAA8D;sBAC1C,MAAM;;;;YA5JhB,MAAM,OAAO;YACb,CAAC,EAAE,WAAW,EAAE,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO;EAghB3D,CAAC;AACL,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
{"version":3,"file":"OperationCodeSample.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/operation-code-sample/components/OperationCodeSample.vue"],"names":[],"mappings":"AAifA,OAAO,KAAK,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,mCAAmC,CAAA;AAErF,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACxD,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAEvE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yCAAyC,CAAA;AACzF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qEAAqE,CAAA;AACxG,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACb,MAAM,8DAA8D,CAAA;AAiBrE,OAAO,KAAK,EAEV,iBAAiB,EAElB,MAAM,yCAAyC,CAAA;AAMhD,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;OAGG;IACH,WAAW,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAA;IACpC;;OAEG;IACH,aAAa,EAAE,iBAAiB,EAAE,CAAA;IAClC;;;;OAIG;IACH,cAAc,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAA;IACzC;;OAEG;IACH,cAAc,CAAC,EAAE,YAAY,GAAG,IAAI,CAAA;IACpC;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;OAEG;IACH,QAAQ,EAAE,iBAAiB,CAAA;IAC3B;;OAEG;IACH,eAAe,EAAE,0BAA0B,EAAE,CAAA;IAC7C;;OAEG;IACH,MAAM,EAAE,cAAc,CAAA;IACtB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,SAAS,EAAE,eAAe,CAAA;IAC1B;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,MAAM,CAAA;IAC5B;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;OAEG;IACH,aAAa,CAAC,EAAE,aAAa,EAAE,CAAA;IAC/B;;;OAGG;IACH,+BAA+B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACzD,CAAA;AAED;;;;;;;;GAQG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;IA4LlB,8DAA8D;sBAC1C,MAAM;;;;IAD1B,8DAA8D;sBAC1C,MAAM;;;;YAxKhB,MAAM,OAAO;YACb,CAAC,EAAE,WAAW,EAAE,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO;EA4hB3D,CAAC;AACL,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}

@@ -5,3 +5,3 @@ import _plugin_vue_export_helper_default from "../../../../_virtual/_plugin-vue_export-helper.js";

//#region src/v2/blocks/operation-code-sample/components/OperationCodeSample.vue
var OperationCodeSample_default = /* @__PURE__ */ _plugin_vue_export_helper_default(OperationCodeSample_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-0e4ddc16"]]);
var OperationCodeSample_default = /* @__PURE__ */ _plugin_vue_export_helper_default(OperationCodeSample_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-59da314d"]]);
//#endregion

@@ -8,0 +8,0 @@ export { OperationCodeSample_default as default };

@@ -1,1 +0,1 @@

{"version":3,"file":"OperationCodeSample.vue.js","names":[],"sources":["../../../../../src/v2/blocks/operation-code-sample/components/OperationCodeSample.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type OperationCodeSampleProps = {\n /**\n * Integration type: determines if the code sample is displayed in a client environment\n * or in an API reference environment.\n */\n integration?: 'client' | 'reference'\n /**\n * List of all http clients formatted into option groups for the client selector\n */\n clientOptions: ClientOptionGroup[]\n /**\n * Pre-selected client, this will determine which client is initially selected in the dropdown\n *\n * @defaults to shell/curl or a custom sample if one is available\n */\n selectedClient?: AvailableClients[number]\n /**\n * Which server from the spec to use for the code example\n */\n selectedServer?: ServerObject | null\n /**\n * The selected content type from the requestBody.content, this will determine which examples are available\n * as well as the content type of the code example\n *\n * @defaults to the first content type if not provided\n */\n selectedContentType?: string\n /**\n * Example name to use for resolving example values for parameters AND requestBody\n *\n * @example \"limited\"\n * ```ts\n * parameters: {\n * name: 'foobar',\n * in: 'query',\n * examples: {\n * limited: {\n * dataValue: 10,\n * }\n * }\n * },\n * body: {\n * content: {\n * 'application/json': {\n * examples: {\n * limited: {\n * dataValue: { foo: 'bar' },\n * }\n * }\n * }\n * }\n * }\n *\n * ```\n */\n selectedExample?: string\n /**\n * Event bus\n */\n eventBus: WorkspaceEventBus\n /**\n * The security schemes which are applicable to this operation\n */\n securitySchemes: SecuritySchemeObjectSecret[]\n /**\n * HTTP method of the operation\n */\n method: HttpMethodType\n /**\n * Path of the operation\n */\n path: string\n /**\n * De-referenced OpenAPI Operation object\n */\n operation: OperationObject\n /**\n * If true and there's no example, we will display a small card with the method and path only\n */\n fallback?: boolean\n /**\n * A method to generate the label of the block, should return an html string\n */\n generateLabel?: () => string\n /**\n * If true, render this as a webhook request example\n */\n isWebhook?: boolean\n /**\n * Workspace + document cookies\n */\n globalCookies?: XScalarCookie[]\n /**\n * When the request body schema uses oneOf/anyOf, use these selected variants\n * for the example snippet (e.g. from the schema dropdowns in the API reference).\n */\n requestBodyCompositionSelection?: Record<string, number>\n}\n\n/**\n * Request Example\n *\n * The core component for rendering a request example block,\n * this component does not have much of its own state but operates on props and custom events\n *\n * @event workspace:update:selected-client - Emitted when the selected client changes\n * @event scalar-update-selected-example - removed for now, we can bring it back when we need it\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarCard,\n ScalarCardFooter,\n ScalarCardHeader,\n ScalarCardSection,\n ScalarCodeBlock,\n ScalarCombobox,\n ScalarVirtualText,\n} from '@scalar/components'\nimport { freezeElement } from '@scalar/helpers/dom/freeze-element'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport { type AvailableClients } from '@scalar/snippetz'\nimport { type WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport type { SecuritySchemeObjectSecret } from '@scalar/workspace-store/request-example'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type {\n OperationObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { operationToHar } from '@v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har'\nimport {\n computed,\n onBeforeMount,\n ref,\n useId,\n watch,\n type ComponentPublicInstance,\n} from 'vue'\n\nimport HttpMethod from '@/v2/blocks/operation-code-sample/components/HttpMethod.vue'\nimport { filterClientsByQuery } from '@/v2/blocks/operation-code-sample/helpers/filter-clients-by-query'\nimport { findClient } from '@/v2/blocks/operation-code-sample/helpers/find-client'\nimport { getClients } from '@/v2/blocks/operation-code-sample/helpers/get-clients'\nimport { getCustomCodeSamples } from '@/v2/blocks/operation-code-sample/helpers/get-custom-code-samples'\nimport { getSecrets } from '@/v2/blocks/operation-code-sample/helpers/get-secrets'\nimport type {\n ClientOption,\n ClientOptionGroup,\n CustomClientOption,\n} from '@/v2/blocks/operation-code-sample/types'\n\nimport { generateCodeSnippet } from '../helpers/generate-code-snippet'\nimport ExamplePicker from './ExamplePicker.vue'\n\nconst {\n integration,\n clientOptions,\n selectedClient,\n selectedServer = null,\n selectedContentType,\n securitySchemes = [],\n method,\n eventBus,\n path,\n operation,\n isWebhook,\n generateLabel,\n globalCookies,\n requestBodyCompositionSelection,\n} = defineProps<OperationCodeSampleProps>()\n\ndefineSlots<{\n header: () => unknown\n footer: ({ exampleName }: { exampleName: string }) => unknown\n}>()\n\n/** Grab the examples for the given content type */\nconst requestBodyExamples = computed(() => {\n const content = getResolvedRef(operation.requestBody)?.content ?? {}\n const contentType = selectedContentType || Object.keys(content)[0]\n if (!contentType) return {}\n\n const examples = content[contentType]?.examples ?? {}\n\n return examples\n})\n\n/** The currently selected example key with v-model support */\nconst selectedExampleKey = defineModel<string>('selectedExample', {\n default: '',\n})\n\n// Set default value to the first example\nonBeforeMount(() => {\n selectedExampleKey.value ||= Object.keys(requestBodyExamples.value)[0] ?? ''\n})\n\n/** Grab any custom code samples from the operation */\nconst customCodeSamples = computed(() => getCustomCodeSamples(operation))\n\n/** Merge custom code samples with the client options */\nconst clients = computed(() =>\n getClients(customCodeSamples.value, clientOptions),\n)\n\n/** The locally selected client which would include code samples from this operation only */\nconst localSelectedClient = ref<ClientOption | CustomClientOption | undefined>(\n findClient(clients.value, selectedClient),\n)\n\n/** If the globally selected client changes we can update the local one */\nwatch(\n () => selectedClient,\n (newClient) => {\n const client = findClient(clients.value, newClient)\n if (client) {\n localSelectedClient.value = client\n }\n },\n)\n\n/** Generate HAR data for webhook requests */\nconst webhookHar = computed(() => {\n if (!isWebhook) return null\n\n try {\n return operationToHar({\n operation,\n method,\n path,\n example: selectedExampleKey.value,\n requestBodyCompositionSelection,\n defaultDisabledParameters: false,\n })\n } catch (error) {\n console.error('[webhookHar]', error)\n return null\n }\n})\n\n/** Generate the code snippet for the selected example */\nconst generatedCode = computed<string>(() => {\n if (isWebhook) {\n return webhookHar.value?.postData?.text ?? ''\n }\n\n return generateCodeSnippet({\n defaultDisabledParameters: false,\n includeDefaultHeaders: integration === 'client',\n clientId: localSelectedClient.value?.id,\n customCodeSamples: customCodeSamples.value,\n operation,\n method,\n path,\n contentType: selectedContentType,\n server: selectedServer,\n securitySchemes,\n example: selectedExampleKey.value,\n globalCookies,\n requestBodyCompositionSelection,\n })\n})\n\n/** The language for the code block, used for syntax highlighting */\nconst codeBlockLanguage = computed(() => {\n if (isWebhook) {\n return webhookLanguage.value\n }\n\n return localSelectedClient.value?.lang\n})\n\n/** Determine the language for webhook content based on MIME type */\nconst webhookLanguage = computed<string>(() => {\n if (!webhookHar.value?.postData) return 'json'\n\n const contentType = webhookHar.value.postData.mimeType\n if (contentType?.includes('json')) return 'json'\n if (contentType?.includes('xml')) return 'xml'\n if (contentType?.includes('yaml') || contentType?.includes('yml'))\n return 'yaml'\n if (contentType?.includes('text/plain')) return 'text'\n\n return 'json'\n})\n\n/** Block secrets from being shown in the code block */\nconst secretCredentials = computed(() => getSecrets(securitySchemes))\n\n/** Grab the ref to freeze the ui as the clients change so there's no jump as the size of the dom changes */\nconst elem = ref<ComponentPublicInstance | null>(null)\n\n/** Set custom example, or update the selected HTTP client globally */\nconst selectClient = (option: ClientOption) => {\n // We need to freeze the ui to prevent scrolling as the clients change\n if (elem.value) {\n const unfreeze = freezeElement(elem.value.$el)\n setTimeout(() => {\n unfreeze()\n }, 300)\n }\n // Update to the local example\n localSelectedClient.value = option\n\n // Emit the change if it's not a custom example\n if (option && !option.id.startsWith('custom')) {\n eventBus.emit('workspace:update:selected-client', option.id)\n }\n}\n\n// Virtualize the code block if it's too large\n// This prevents the entire app from freezing up if there's a massive example\n// We set a lower threshold here as code examples can get quite large\nconst VIRTUALIZATION_THRESHOLD = 20_000\n\nconst shouldVirtualize = computed(\n () => (generatedCode.value.length ?? 0) > VIRTUALIZATION_THRESHOLD,\n)\n\nconst id = useId()\n</script>\n<template>\n <ScalarCard\n v-if=\"generatedCode\"\n ref=\"elem\"\n class=\"request-card dark-mode\">\n <!-- Header -->\n <ScalarCardHeader class=\"pr-2.5\">\n <span class=\"sr-only\">Request Example for</span>\n <HttpMethod\n as=\"span\"\n class=\"request-method\"\n :method=\"method\" />\n <span\n v-if=\"generateLabel\"\n v-html=\"generateLabel()\" />\n <slot name=\"header\" />\n <!-- Client picker -->\n <template\n v-if=\"!isWebhook && clients.length\"\n #actions>\n <ScalarCombobox\n class=\"max-h-80\"\n :filterFn=\"filterClientsByQuery\"\n :modelValue=\"localSelectedClient\"\n :options=\"clients\"\n placement=\"bottom-end\"\n teleport\n @update:modelValue=\"selectClient($event as ClientOption)\">\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex h-full w-fit gap-1.5 px-0.5 py-0 text-base font-normal\"\n data-testid=\"client-picker\"\n variant=\"ghost\">\n {{ localSelectedClient?.title }}\n <ScalarIconCaretDown\n class=\"ui-open:rotate-180 mt-px size-3 transition-transform duration-100\"\n weight=\"bold\" />\n </ScalarButton>\n </ScalarCombobox>\n </template>\n </ScalarCardHeader>\n\n <!-- Code snippet -->\n <ScalarCardSection class=\"request-editor-section custom-scroll p-0\">\n <div\n :id=\"`${id}-example`\"\n class=\"code-snippet\">\n <ScalarCodeBlock\n v-if=\"!shouldVirtualize\"\n class=\"bg-b-2 h-full\"\n :content=\"generatedCode\"\n :hideCredentials=\"secretCredentials\"\n :lang=\"codeBlockLanguage\"\n lineNumbers />\n <ScalarVirtualText\n v-else\n containerClass=\"custom-scroll scalar-code-block border rounded-b flex flex-1 max-h-screen\"\n contentClass=\"language-plaintext whitespace-pre font-code text-base\"\n :lineHeight=\"20\"\n :text=\"generatedCode\" />\n </div>\n </ScalarCardSection>\n\n <!-- Footer -->\n <ScalarCardFooter\n v-if=\"Object.keys(requestBodyExamples).length > 1 || $slots.footer\"\n class=\"request-card-footer bg-b-3\">\n <!-- Example picker -->\n <div\n v-if=\"Object.keys(requestBodyExamples).length > 1\"\n class=\"request-card-footer-addon\">\n <template v-if=\"Object.keys(requestBodyExamples).length\">\n <ExamplePicker\n v-model=\"selectedExampleKey\"\n :examples=\"requestBodyExamples\" />\n </template>\n </div>\n\n <!-- Footer -->\n <slot\n :exampleName=\"selectedExampleKey\"\n name=\"footer\" />\n </ScalarCardFooter>\n </ScalarCard>\n\n <!-- Fallback card with just method and path in the case of no examples -->\n <ScalarCard\n v-else-if=\"fallback\"\n class=\"request-card dark-mode\">\n <ScalarCardSection class=\"request-card-simple\">\n <div class=\"request-header\">\n <HttpMethod\n as=\"span\"\n class=\"request-method\"\n :method=\"method\" />\n <slot name=\"header\" />\n </div>\n <slot\n :exampleName=\"selectedExampleKey\"\n name=\"footer\" />\n </ScalarCardSection>\n </ScalarCard>\n</template>\n<style scoped>\n.request-card {\n font-size: var(--scalar-font-size-3);\n}\n.request-method {\n font-family: var(--scalar-font-code);\n text-transform: uppercase;\n margin-right: 6px;\n}\n.request-card-footer {\n display: flex;\n justify-content: flex-end;\n padding: 6px;\n flex-shrink: 0;\n position: relative;\n}\n.request-card-footer-addon {\n display: flex;\n align-items: center;\n\n flex: 1;\n min-width: 0;\n}\n.request-editor-section {\n display: flex;\n flex: 1;\n}\n.request-card-simple {\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n padding: 8px 8px 8px 12px;\n\n font-size: var(--scalar-small);\n}\n.code-snippet {\n display: flex;\n flex-direction: column;\n width: 100%;\n}\n</style>\n"],"mappings":""}
{"version":3,"file":"OperationCodeSample.vue.js","names":[],"sources":["../../../../../src/v2/blocks/operation-code-sample/components/OperationCodeSample.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type OperationCodeSampleProps = {\n /**\n * Integration type: determines if the code sample is displayed in a client environment\n * or in an API reference environment.\n */\n integration?: 'client' | 'reference'\n /**\n * List of all http clients formatted into option groups for the client selector\n */\n clientOptions: ClientOptionGroup[]\n /**\n * Pre-selected client, this will determine which client is initially selected in the dropdown\n *\n * @defaults to shell/curl or a custom sample if one is available\n */\n selectedClient?: AvailableClients[number]\n /**\n * Which server from the spec to use for the code example\n */\n selectedServer?: ServerObject | null\n /**\n * The selected content type from the requestBody.content, this will determine which examples are available\n * as well as the content type of the code example\n *\n * @defaults to the first content type if not provided\n */\n selectedContentType?: string\n /**\n * Example name to use for resolving example values for parameters AND requestBody\n *\n * @example \"limited\"\n * ```ts\n * parameters: {\n * name: 'foobar',\n * in: 'query',\n * examples: {\n * limited: {\n * dataValue: 10,\n * }\n * }\n * },\n * body: {\n * content: {\n * 'application/json': {\n * examples: {\n * limited: {\n * dataValue: { foo: 'bar' },\n * }\n * }\n * }\n * }\n * }\n *\n * ```\n */\n selectedExample?: string\n /**\n * Event bus\n */\n eventBus: WorkspaceEventBus\n /**\n * The security schemes which are applicable to this operation\n */\n securitySchemes: SecuritySchemeObjectSecret[]\n /**\n * HTTP method of the operation\n */\n method: HttpMethodType\n /**\n * Path of the operation\n */\n path: string\n /**\n * De-referenced OpenAPI Operation object\n */\n operation: OperationObject\n /**\n * If true and there's no example, we will display a small card with the method and path only\n */\n fallback?: boolean\n /**\n * A method to generate the label of the block, should return an html string\n */\n generateLabel?: () => string\n /**\n * If true, render this as a webhook request example\n */\n isWebhook?: boolean\n /**\n * Workspace + document cookies\n */\n globalCookies?: XScalarCookie[]\n /**\n * When the request body schema uses oneOf/anyOf, use these selected variants\n * for the example snippet (e.g. from the schema dropdowns in the API reference).\n */\n requestBodyCompositionSelection?: Record<string, number>\n}\n\n/**\n * Request Example\n *\n * The core component for rendering a request example block,\n * this component does not have much of its own state but operates on props and custom events\n *\n * @event workspace:update:selected-client - Emitted when the selected client changes\n * @event scalar-update-selected-example - removed for now, we can bring it back when we need it\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarCard,\n ScalarCardFooter,\n ScalarCardHeader,\n ScalarCardSection,\n ScalarCodeBlock,\n ScalarCombobox,\n ScalarVirtualText,\n} from '@scalar/components'\nimport { freezeElement } from '@scalar/helpers/dom/freeze-element'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport { type AvailableClients } from '@scalar/snippetz'\nimport { type WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport type { SecuritySchemeObjectSecret } from '@scalar/workspace-store/request-example'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type {\n OperationObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { operationToHar } from '@v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har'\nimport {\n computed,\n onBeforeMount,\n ref,\n useId,\n watch,\n type ComponentPublicInstance,\n} from 'vue'\n\nimport HttpMethod from '@/v2/blocks/operation-code-sample/components/HttpMethod.vue'\nimport { filterClientsByQuery } from '@/v2/blocks/operation-code-sample/helpers/filter-clients-by-query'\nimport { findClient } from '@/v2/blocks/operation-code-sample/helpers/find-client'\nimport { getClients } from '@/v2/blocks/operation-code-sample/helpers/get-clients'\nimport { getCustomCodeSamples } from '@/v2/blocks/operation-code-sample/helpers/get-custom-code-samples'\nimport { getSecrets } from '@/v2/blocks/operation-code-sample/helpers/get-secrets'\nimport type {\n ClientOption,\n ClientOptionGroup,\n CustomClientOption,\n} from '@/v2/blocks/operation-code-sample/types'\n\nimport { generateCodeSnippet } from '../helpers/generate-code-snippet'\nimport ExamplePicker from './ExamplePicker.vue'\n\nconst {\n integration,\n clientOptions,\n selectedClient,\n selectedServer = null,\n selectedContentType,\n securitySchemes = [],\n method,\n eventBus,\n path,\n operation,\n isWebhook,\n generateLabel,\n globalCookies,\n requestBodyCompositionSelection,\n} = defineProps<OperationCodeSampleProps>()\n\ndefineSlots<{\n header: () => unknown\n footer: ({ exampleName }: { exampleName: string }) => unknown\n}>()\n\n/** Grab the examples for the given content type */\nconst requestBodyExamples = computed(() => {\n const content = getResolvedRef(operation.requestBody)?.content ?? {}\n const contentType = selectedContentType || Object.keys(content)[0]\n if (!contentType) return {}\n\n const examples = content[contentType]?.examples ?? {}\n\n return examples\n})\n\n/** The currently selected example key with v-model support */\nconst selectedExampleKey = defineModel<string>('selectedExample', {\n default: '',\n})\n\n// Set default value to the first example\nonBeforeMount(() => {\n selectedExampleKey.value ||= Object.keys(requestBodyExamples.value)[0] ?? ''\n})\n\n/** Reset the selected example key if the content type changes and the new content type doesn't have the previously selected example */\nwatch(\n () => selectedContentType,\n () => {\n if (\n !Object.keys(requestBodyExamples.value).includes(selectedExampleKey.value)\n ) {\n selectedExampleKey.value = Object.keys(requestBodyExamples.value)[0] ?? ''\n }\n },\n)\n\n/** Grab any custom code samples from the operation */\nconst customCodeSamples = computed(() => getCustomCodeSamples(operation))\n\n/** Merge custom code samples with the client options */\nconst clients = computed(() =>\n getClients(customCodeSamples.value, clientOptions),\n)\n\n/** The locally selected client which would include code samples from this operation only */\nconst localSelectedClient = ref<ClientOption | CustomClientOption | undefined>(\n findClient(clients.value, selectedClient),\n)\n\n/** If the globally selected client changes we can update the local one */\nwatch(\n () => selectedClient,\n (newClient) => {\n const client = findClient(clients.value, newClient)\n if (client) {\n localSelectedClient.value = client\n }\n },\n)\n\n/** Generate HAR data for webhook requests */\nconst webhookHar = computed(() => {\n if (!isWebhook) return null\n\n try {\n return operationToHar({\n operation,\n method,\n path,\n example: selectedExampleKey.value,\n requestBodyCompositionSelection,\n defaultDisabledParameters: false,\n })\n } catch (error) {\n console.error('[webhookHar]', error)\n return null\n }\n})\n\n/** Generate the code snippet for the selected example */\nconst generatedCode = computed<string>(() => {\n if (isWebhook) {\n return webhookHar.value?.postData?.text ?? ''\n }\n\n return generateCodeSnippet({\n defaultDisabledParameters: false,\n includeDefaultHeaders: integration === 'client',\n clientId: localSelectedClient.value?.id,\n customCodeSamples: customCodeSamples.value,\n operation,\n method,\n path,\n contentType: selectedContentType,\n server: selectedServer,\n securitySchemes,\n example: selectedExampleKey.value,\n globalCookies,\n requestBodyCompositionSelection,\n })\n})\n\n/** The language for the code block, used for syntax highlighting */\nconst codeBlockLanguage = computed(() => {\n if (isWebhook) {\n return webhookLanguage.value\n }\n\n return localSelectedClient.value?.lang\n})\n\n/** Determine the language for webhook content based on MIME type */\nconst webhookLanguage = computed<string>(() => {\n if (!webhookHar.value?.postData) return 'json'\n\n const contentType = webhookHar.value.postData.mimeType\n if (contentType?.includes('json')) return 'json'\n if (contentType?.includes('xml')) return 'xml'\n if (contentType?.includes('yaml') || contentType?.includes('yml'))\n return 'yaml'\n if (contentType?.includes('text/plain')) return 'text'\n\n return 'json'\n})\n\n/** Block secrets from being shown in the code block */\nconst secretCredentials = computed(() => getSecrets(securitySchemes))\n\n/** Grab the ref to freeze the ui as the clients change so there's no jump as the size of the dom changes */\nconst elem = ref<ComponentPublicInstance | null>(null)\n\n/** Set custom example, or update the selected HTTP client globally */\nconst selectClient = (option: ClientOption) => {\n // We need to freeze the ui to prevent scrolling as the clients change\n if (elem.value) {\n const unfreeze = freezeElement(elem.value.$el)\n setTimeout(() => {\n unfreeze()\n }, 300)\n }\n // Update to the local example\n localSelectedClient.value = option\n\n // Emit the change if it's not a custom example\n if (option && !option.id.startsWith('custom')) {\n eventBus.emit('workspace:update:selected-client', option.id)\n }\n}\n\n// Virtualize the code block if it's too large\n// This prevents the entire app from freezing up if there's a massive example\n// We set a lower threshold here as code examples can get quite large\nconst VIRTUALIZATION_THRESHOLD = 20_000\n\nconst shouldVirtualize = computed(\n () => (generatedCode.value.length ?? 0) > VIRTUALIZATION_THRESHOLD,\n)\n\nconst id = useId()\n</script>\n<template>\n <ScalarCard\n v-if=\"generatedCode\"\n ref=\"elem\"\n class=\"request-card dark-mode\">\n <!-- Header -->\n <ScalarCardHeader class=\"pr-2.5\">\n <span class=\"sr-only\">Request Example for</span>\n <HttpMethod\n as=\"span\"\n class=\"request-method\"\n :method=\"method\" />\n <span\n v-if=\"generateLabel\"\n v-html=\"generateLabel()\" />\n <slot name=\"header\" />\n <!-- Client picker -->\n <template\n v-if=\"!isWebhook && clients.length\"\n #actions>\n <ScalarCombobox\n class=\"max-h-80\"\n :filterFn=\"filterClientsByQuery\"\n :modelValue=\"localSelectedClient\"\n :options=\"clients\"\n placement=\"bottom-end\"\n teleport\n @update:modelValue=\"selectClient($event as ClientOption)\">\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex h-full w-fit gap-1.5 px-0.5 py-0 text-base font-normal\"\n data-testid=\"client-picker\"\n variant=\"ghost\">\n {{ localSelectedClient?.title }}\n <ScalarIconCaretDown\n class=\"ui-open:rotate-180 mt-px size-3 transition-transform duration-100\"\n weight=\"bold\" />\n </ScalarButton>\n </ScalarCombobox>\n </template>\n </ScalarCardHeader>\n\n <!-- Code snippet -->\n <ScalarCardSection class=\"request-editor-section custom-scroll p-0\">\n <div\n :id=\"`${id}-example`\"\n class=\"code-snippet\">\n <ScalarCodeBlock\n v-if=\"!shouldVirtualize\"\n class=\"bg-b-2 h-full\"\n :content=\"generatedCode\"\n :hideCredentials=\"secretCredentials\"\n :lang=\"codeBlockLanguage\"\n lineNumbers />\n <ScalarVirtualText\n v-else\n containerClass=\"custom-scroll scalar-code-block border rounded-b flex flex-1 max-h-screen\"\n contentClass=\"language-plaintext whitespace-pre font-code text-base\"\n :lineHeight=\"20\"\n :text=\"generatedCode\" />\n </div>\n </ScalarCardSection>\n\n <!-- Footer -->\n <ScalarCardFooter\n v-if=\"Object.keys(requestBodyExamples).length > 1 || $slots.footer\"\n class=\"request-card-footer bg-b-3\">\n <!-- Example picker -->\n <div\n v-if=\"Object.keys(requestBodyExamples).length > 1\"\n class=\"request-card-footer-addon\">\n <template v-if=\"Object.keys(requestBodyExamples).length\">\n <ExamplePicker\n v-model=\"selectedExampleKey\"\n :examples=\"requestBodyExamples\" />\n </template>\n </div>\n\n <!-- Footer -->\n <slot\n :exampleName=\"selectedExampleKey\"\n name=\"footer\" />\n </ScalarCardFooter>\n </ScalarCard>\n\n <!-- Fallback card with just method and path in the case of no examples -->\n <ScalarCard\n v-else-if=\"fallback\"\n class=\"request-card dark-mode\">\n <ScalarCardSection class=\"request-card-simple\">\n <div class=\"request-header\">\n <HttpMethod\n as=\"span\"\n class=\"request-method\"\n :method=\"method\" />\n <slot name=\"header\" />\n </div>\n <slot\n :exampleName=\"selectedExampleKey\"\n name=\"footer\" />\n </ScalarCardSection>\n </ScalarCard>\n</template>\n<style scoped>\n.request-card {\n font-size: var(--scalar-font-size-3);\n}\n.request-method {\n font-family: var(--scalar-font-code);\n text-transform: uppercase;\n margin-right: 6px;\n}\n.request-card-footer {\n display: flex;\n justify-content: flex-end;\n padding: 6px;\n flex-shrink: 0;\n position: relative;\n}\n.request-card-footer-addon {\n display: flex;\n align-items: center;\n\n flex: 1;\n min-width: 0;\n}\n.request-editor-section {\n display: flex;\n flex: 1;\n}\n.request-card-simple {\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n padding: 8px 8px 8px 12px;\n\n font-size: var(--scalar-small);\n}\n.code-snippet {\n display: flex;\n flex-direction: column;\n width: 100%;\n}\n</style>\n"],"mappings":""}

@@ -60,2 +60,6 @@ import ExamplePicker_default from "./ExamplePicker.vue.js";

});
/** Reset the selected example key if the content type changes and the new content type doesn't have the previously selected example */
watch(() => __props.selectedContentType, () => {
if (!Object.keys(requestBodyExamples.value).includes(selectedExampleKey.value)) selectedExampleKey.value = Object.keys(requestBodyExamples.value)[0] ?? "";
});
/** Grab any custom code samples from the operation */

@@ -62,0 +66,0 @@ const customCodeSamples = computed(() => getCustomCodeSamples(__props.operation));

@@ -1,1 +0,1 @@

{"version":3,"file":"OperationCodeSample.vue.script.js","names":["$slots"],"sources":["../../../../../src/v2/blocks/operation-code-sample/components/OperationCodeSample.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type OperationCodeSampleProps = {\n /**\n * Integration type: determines if the code sample is displayed in a client environment\n * or in an API reference environment.\n */\n integration?: 'client' | 'reference'\n /**\n * List of all http clients formatted into option groups for the client selector\n */\n clientOptions: ClientOptionGroup[]\n /**\n * Pre-selected client, this will determine which client is initially selected in the dropdown\n *\n * @defaults to shell/curl or a custom sample if one is available\n */\n selectedClient?: AvailableClients[number]\n /**\n * Which server from the spec to use for the code example\n */\n selectedServer?: ServerObject | null\n /**\n * The selected content type from the requestBody.content, this will determine which examples are available\n * as well as the content type of the code example\n *\n * @defaults to the first content type if not provided\n */\n selectedContentType?: string\n /**\n * Example name to use for resolving example values for parameters AND requestBody\n *\n * @example \"limited\"\n * ```ts\n * parameters: {\n * name: 'foobar',\n * in: 'query',\n * examples: {\n * limited: {\n * dataValue: 10,\n * }\n * }\n * },\n * body: {\n * content: {\n * 'application/json': {\n * examples: {\n * limited: {\n * dataValue: { foo: 'bar' },\n * }\n * }\n * }\n * }\n * }\n *\n * ```\n */\n selectedExample?: string\n /**\n * Event bus\n */\n eventBus: WorkspaceEventBus\n /**\n * The security schemes which are applicable to this operation\n */\n securitySchemes: SecuritySchemeObjectSecret[]\n /**\n * HTTP method of the operation\n */\n method: HttpMethodType\n /**\n * Path of the operation\n */\n path: string\n /**\n * De-referenced OpenAPI Operation object\n */\n operation: OperationObject\n /**\n * If true and there's no example, we will display a small card with the method and path only\n */\n fallback?: boolean\n /**\n * A method to generate the label of the block, should return an html string\n */\n generateLabel?: () => string\n /**\n * If true, render this as a webhook request example\n */\n isWebhook?: boolean\n /**\n * Workspace + document cookies\n */\n globalCookies?: XScalarCookie[]\n /**\n * When the request body schema uses oneOf/anyOf, use these selected variants\n * for the example snippet (e.g. from the schema dropdowns in the API reference).\n */\n requestBodyCompositionSelection?: Record<string, number>\n}\n\n/**\n * Request Example\n *\n * The core component for rendering a request example block,\n * this component does not have much of its own state but operates on props and custom events\n *\n * @event workspace:update:selected-client - Emitted when the selected client changes\n * @event scalar-update-selected-example - removed for now, we can bring it back when we need it\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarCard,\n ScalarCardFooter,\n ScalarCardHeader,\n ScalarCardSection,\n ScalarCodeBlock,\n ScalarCombobox,\n ScalarVirtualText,\n} from '@scalar/components'\nimport { freezeElement } from '@scalar/helpers/dom/freeze-element'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport { type AvailableClients } from '@scalar/snippetz'\nimport { type WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport type { SecuritySchemeObjectSecret } from '@scalar/workspace-store/request-example'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type {\n OperationObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { operationToHar } from '@v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har'\nimport {\n computed,\n onBeforeMount,\n ref,\n useId,\n watch,\n type ComponentPublicInstance,\n} from 'vue'\n\nimport HttpMethod from '@/v2/blocks/operation-code-sample/components/HttpMethod.vue'\nimport { filterClientsByQuery } from '@/v2/blocks/operation-code-sample/helpers/filter-clients-by-query'\nimport { findClient } from '@/v2/blocks/operation-code-sample/helpers/find-client'\nimport { getClients } from '@/v2/blocks/operation-code-sample/helpers/get-clients'\nimport { getCustomCodeSamples } from '@/v2/blocks/operation-code-sample/helpers/get-custom-code-samples'\nimport { getSecrets } from '@/v2/blocks/operation-code-sample/helpers/get-secrets'\nimport type {\n ClientOption,\n ClientOptionGroup,\n CustomClientOption,\n} from '@/v2/blocks/operation-code-sample/types'\n\nimport { generateCodeSnippet } from '../helpers/generate-code-snippet'\nimport ExamplePicker from './ExamplePicker.vue'\n\nconst {\n integration,\n clientOptions,\n selectedClient,\n selectedServer = null,\n selectedContentType,\n securitySchemes = [],\n method,\n eventBus,\n path,\n operation,\n isWebhook,\n generateLabel,\n globalCookies,\n requestBodyCompositionSelection,\n} = defineProps<OperationCodeSampleProps>()\n\ndefineSlots<{\n header: () => unknown\n footer: ({ exampleName }: { exampleName: string }) => unknown\n}>()\n\n/** Grab the examples for the given content type */\nconst requestBodyExamples = computed(() => {\n const content = getResolvedRef(operation.requestBody)?.content ?? {}\n const contentType = selectedContentType || Object.keys(content)[0]\n if (!contentType) return {}\n\n const examples = content[contentType]?.examples ?? {}\n\n return examples\n})\n\n/** The currently selected example key with v-model support */\nconst selectedExampleKey = defineModel<string>('selectedExample', {\n default: '',\n})\n\n// Set default value to the first example\nonBeforeMount(() => {\n selectedExampleKey.value ||= Object.keys(requestBodyExamples.value)[0] ?? ''\n})\n\n/** Grab any custom code samples from the operation */\nconst customCodeSamples = computed(() => getCustomCodeSamples(operation))\n\n/** Merge custom code samples with the client options */\nconst clients = computed(() =>\n getClients(customCodeSamples.value, clientOptions),\n)\n\n/** The locally selected client which would include code samples from this operation only */\nconst localSelectedClient = ref<ClientOption | CustomClientOption | undefined>(\n findClient(clients.value, selectedClient),\n)\n\n/** If the globally selected client changes we can update the local one */\nwatch(\n () => selectedClient,\n (newClient) => {\n const client = findClient(clients.value, newClient)\n if (client) {\n localSelectedClient.value = client\n }\n },\n)\n\n/** Generate HAR data for webhook requests */\nconst webhookHar = computed(() => {\n if (!isWebhook) return null\n\n try {\n return operationToHar({\n operation,\n method,\n path,\n example: selectedExampleKey.value,\n requestBodyCompositionSelection,\n defaultDisabledParameters: false,\n })\n } catch (error) {\n console.error('[webhookHar]', error)\n return null\n }\n})\n\n/** Generate the code snippet for the selected example */\nconst generatedCode = computed<string>(() => {\n if (isWebhook) {\n return webhookHar.value?.postData?.text ?? ''\n }\n\n return generateCodeSnippet({\n defaultDisabledParameters: false,\n includeDefaultHeaders: integration === 'client',\n clientId: localSelectedClient.value?.id,\n customCodeSamples: customCodeSamples.value,\n operation,\n method,\n path,\n contentType: selectedContentType,\n server: selectedServer,\n securitySchemes,\n example: selectedExampleKey.value,\n globalCookies,\n requestBodyCompositionSelection,\n })\n})\n\n/** The language for the code block, used for syntax highlighting */\nconst codeBlockLanguage = computed(() => {\n if (isWebhook) {\n return webhookLanguage.value\n }\n\n return localSelectedClient.value?.lang\n})\n\n/** Determine the language for webhook content based on MIME type */\nconst webhookLanguage = computed<string>(() => {\n if (!webhookHar.value?.postData) return 'json'\n\n const contentType = webhookHar.value.postData.mimeType\n if (contentType?.includes('json')) return 'json'\n if (contentType?.includes('xml')) return 'xml'\n if (contentType?.includes('yaml') || contentType?.includes('yml'))\n return 'yaml'\n if (contentType?.includes('text/plain')) return 'text'\n\n return 'json'\n})\n\n/** Block secrets from being shown in the code block */\nconst secretCredentials = computed(() => getSecrets(securitySchemes))\n\n/** Grab the ref to freeze the ui as the clients change so there's no jump as the size of the dom changes */\nconst elem = ref<ComponentPublicInstance | null>(null)\n\n/** Set custom example, or update the selected HTTP client globally */\nconst selectClient = (option: ClientOption) => {\n // We need to freeze the ui to prevent scrolling as the clients change\n if (elem.value) {\n const unfreeze = freezeElement(elem.value.$el)\n setTimeout(() => {\n unfreeze()\n }, 300)\n }\n // Update to the local example\n localSelectedClient.value = option\n\n // Emit the change if it's not a custom example\n if (option && !option.id.startsWith('custom')) {\n eventBus.emit('workspace:update:selected-client', option.id)\n }\n}\n\n// Virtualize the code block if it's too large\n// This prevents the entire app from freezing up if there's a massive example\n// We set a lower threshold here as code examples can get quite large\nconst VIRTUALIZATION_THRESHOLD = 20_000\n\nconst shouldVirtualize = computed(\n () => (generatedCode.value.length ?? 0) > VIRTUALIZATION_THRESHOLD,\n)\n\nconst id = useId()\n</script>\n<template>\n <ScalarCard\n v-if=\"generatedCode\"\n ref=\"elem\"\n class=\"request-card dark-mode\">\n <!-- Header -->\n <ScalarCardHeader class=\"pr-2.5\">\n <span class=\"sr-only\">Request Example for</span>\n <HttpMethod\n as=\"span\"\n class=\"request-method\"\n :method=\"method\" />\n <span\n v-if=\"generateLabel\"\n v-html=\"generateLabel()\" />\n <slot name=\"header\" />\n <!-- Client picker -->\n <template\n v-if=\"!isWebhook && clients.length\"\n #actions>\n <ScalarCombobox\n class=\"max-h-80\"\n :filterFn=\"filterClientsByQuery\"\n :modelValue=\"localSelectedClient\"\n :options=\"clients\"\n placement=\"bottom-end\"\n teleport\n @update:modelValue=\"selectClient($event as ClientOption)\">\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex h-full w-fit gap-1.5 px-0.5 py-0 text-base font-normal\"\n data-testid=\"client-picker\"\n variant=\"ghost\">\n {{ localSelectedClient?.title }}\n <ScalarIconCaretDown\n class=\"ui-open:rotate-180 mt-px size-3 transition-transform duration-100\"\n weight=\"bold\" />\n </ScalarButton>\n </ScalarCombobox>\n </template>\n </ScalarCardHeader>\n\n <!-- Code snippet -->\n <ScalarCardSection class=\"request-editor-section custom-scroll p-0\">\n <div\n :id=\"`${id}-example`\"\n class=\"code-snippet\">\n <ScalarCodeBlock\n v-if=\"!shouldVirtualize\"\n class=\"bg-b-2 h-full\"\n :content=\"generatedCode\"\n :hideCredentials=\"secretCredentials\"\n :lang=\"codeBlockLanguage\"\n lineNumbers />\n <ScalarVirtualText\n v-else\n containerClass=\"custom-scroll scalar-code-block border rounded-b flex flex-1 max-h-screen\"\n contentClass=\"language-plaintext whitespace-pre font-code text-base\"\n :lineHeight=\"20\"\n :text=\"generatedCode\" />\n </div>\n </ScalarCardSection>\n\n <!-- Footer -->\n <ScalarCardFooter\n v-if=\"Object.keys(requestBodyExamples).length > 1 || $slots.footer\"\n class=\"request-card-footer bg-b-3\">\n <!-- Example picker -->\n <div\n v-if=\"Object.keys(requestBodyExamples).length > 1\"\n class=\"request-card-footer-addon\">\n <template v-if=\"Object.keys(requestBodyExamples).length\">\n <ExamplePicker\n v-model=\"selectedExampleKey\"\n :examples=\"requestBodyExamples\" />\n </template>\n </div>\n\n <!-- Footer -->\n <slot\n :exampleName=\"selectedExampleKey\"\n name=\"footer\" />\n </ScalarCardFooter>\n </ScalarCard>\n\n <!-- Fallback card with just method and path in the case of no examples -->\n <ScalarCard\n v-else-if=\"fallback\"\n class=\"request-card dark-mode\">\n <ScalarCardSection class=\"request-card-simple\">\n <div class=\"request-header\">\n <HttpMethod\n as=\"span\"\n class=\"request-method\"\n :method=\"method\" />\n <slot name=\"header\" />\n </div>\n <slot\n :exampleName=\"selectedExampleKey\"\n name=\"footer\" />\n </ScalarCardSection>\n </ScalarCard>\n</template>\n<style scoped>\n.request-card {\n font-size: var(--scalar-font-size-3);\n}\n.request-method {\n font-family: var(--scalar-font-code);\n text-transform: uppercase;\n margin-right: 6px;\n}\n.request-card-footer {\n display: flex;\n justify-content: flex-end;\n padding: 6px;\n flex-shrink: 0;\n position: relative;\n}\n.request-card-footer-addon {\n display: flex;\n align-items: center;\n\n flex: 1;\n min-width: 0;\n}\n.request-editor-section {\n display: flex;\n flex: 1;\n}\n.request-card-simple {\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n padding: 8px 8px 8px 12px;\n\n font-size: var(--scalar-small);\n}\n.code-snippet {\n display: flex;\n flex-direction: column;\n width: 100%;\n}\n</style>\n"],"mappings":"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"}
{"version":3,"file":"OperationCodeSample.vue.script.js","names":["$slots"],"sources":["../../../../../src/v2/blocks/operation-code-sample/components/OperationCodeSample.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type OperationCodeSampleProps = {\n /**\n * Integration type: determines if the code sample is displayed in a client environment\n * or in an API reference environment.\n */\n integration?: 'client' | 'reference'\n /**\n * List of all http clients formatted into option groups for the client selector\n */\n clientOptions: ClientOptionGroup[]\n /**\n * Pre-selected client, this will determine which client is initially selected in the dropdown\n *\n * @defaults to shell/curl or a custom sample if one is available\n */\n selectedClient?: AvailableClients[number]\n /**\n * Which server from the spec to use for the code example\n */\n selectedServer?: ServerObject | null\n /**\n * The selected content type from the requestBody.content, this will determine which examples are available\n * as well as the content type of the code example\n *\n * @defaults to the first content type if not provided\n */\n selectedContentType?: string\n /**\n * Example name to use for resolving example values for parameters AND requestBody\n *\n * @example \"limited\"\n * ```ts\n * parameters: {\n * name: 'foobar',\n * in: 'query',\n * examples: {\n * limited: {\n * dataValue: 10,\n * }\n * }\n * },\n * body: {\n * content: {\n * 'application/json': {\n * examples: {\n * limited: {\n * dataValue: { foo: 'bar' },\n * }\n * }\n * }\n * }\n * }\n *\n * ```\n */\n selectedExample?: string\n /**\n * Event bus\n */\n eventBus: WorkspaceEventBus\n /**\n * The security schemes which are applicable to this operation\n */\n securitySchemes: SecuritySchemeObjectSecret[]\n /**\n * HTTP method of the operation\n */\n method: HttpMethodType\n /**\n * Path of the operation\n */\n path: string\n /**\n * De-referenced OpenAPI Operation object\n */\n operation: OperationObject\n /**\n * If true and there's no example, we will display a small card with the method and path only\n */\n fallback?: boolean\n /**\n * A method to generate the label of the block, should return an html string\n */\n generateLabel?: () => string\n /**\n * If true, render this as a webhook request example\n */\n isWebhook?: boolean\n /**\n * Workspace + document cookies\n */\n globalCookies?: XScalarCookie[]\n /**\n * When the request body schema uses oneOf/anyOf, use these selected variants\n * for the example snippet (e.g. from the schema dropdowns in the API reference).\n */\n requestBodyCompositionSelection?: Record<string, number>\n}\n\n/**\n * Request Example\n *\n * The core component for rendering a request example block,\n * this component does not have much of its own state but operates on props and custom events\n *\n * @event workspace:update:selected-client - Emitted when the selected client changes\n * @event scalar-update-selected-example - removed for now, we can bring it back when we need it\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarCard,\n ScalarCardFooter,\n ScalarCardHeader,\n ScalarCardSection,\n ScalarCodeBlock,\n ScalarCombobox,\n ScalarVirtualText,\n} from '@scalar/components'\nimport { freezeElement } from '@scalar/helpers/dom/freeze-element'\nimport type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods'\nimport { ScalarIconCaretDown } from '@scalar/icons'\nimport { type AvailableClients } from '@scalar/snippetz'\nimport { type WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport type { SecuritySchemeObjectSecret } from '@scalar/workspace-store/request-example'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type {\n OperationObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { operationToHar } from '@v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har'\nimport {\n computed,\n onBeforeMount,\n ref,\n useId,\n watch,\n type ComponentPublicInstance,\n} from 'vue'\n\nimport HttpMethod from '@/v2/blocks/operation-code-sample/components/HttpMethod.vue'\nimport { filterClientsByQuery } from '@/v2/blocks/operation-code-sample/helpers/filter-clients-by-query'\nimport { findClient } from '@/v2/blocks/operation-code-sample/helpers/find-client'\nimport { getClients } from '@/v2/blocks/operation-code-sample/helpers/get-clients'\nimport { getCustomCodeSamples } from '@/v2/blocks/operation-code-sample/helpers/get-custom-code-samples'\nimport { getSecrets } from '@/v2/blocks/operation-code-sample/helpers/get-secrets'\nimport type {\n ClientOption,\n ClientOptionGroup,\n CustomClientOption,\n} from '@/v2/blocks/operation-code-sample/types'\n\nimport { generateCodeSnippet } from '../helpers/generate-code-snippet'\nimport ExamplePicker from './ExamplePicker.vue'\n\nconst {\n integration,\n clientOptions,\n selectedClient,\n selectedServer = null,\n selectedContentType,\n securitySchemes = [],\n method,\n eventBus,\n path,\n operation,\n isWebhook,\n generateLabel,\n globalCookies,\n requestBodyCompositionSelection,\n} = defineProps<OperationCodeSampleProps>()\n\ndefineSlots<{\n header: () => unknown\n footer: ({ exampleName }: { exampleName: string }) => unknown\n}>()\n\n/** Grab the examples for the given content type */\nconst requestBodyExamples = computed(() => {\n const content = getResolvedRef(operation.requestBody)?.content ?? {}\n const contentType = selectedContentType || Object.keys(content)[0]\n if (!contentType) return {}\n\n const examples = content[contentType]?.examples ?? {}\n\n return examples\n})\n\n/** The currently selected example key with v-model support */\nconst selectedExampleKey = defineModel<string>('selectedExample', {\n default: '',\n})\n\n// Set default value to the first example\nonBeforeMount(() => {\n selectedExampleKey.value ||= Object.keys(requestBodyExamples.value)[0] ?? ''\n})\n\n/** Reset the selected example key if the content type changes and the new content type doesn't have the previously selected example */\nwatch(\n () => selectedContentType,\n () => {\n if (\n !Object.keys(requestBodyExamples.value).includes(selectedExampleKey.value)\n ) {\n selectedExampleKey.value = Object.keys(requestBodyExamples.value)[0] ?? ''\n }\n },\n)\n\n/** Grab any custom code samples from the operation */\nconst customCodeSamples = computed(() => getCustomCodeSamples(operation))\n\n/** Merge custom code samples with the client options */\nconst clients = computed(() =>\n getClients(customCodeSamples.value, clientOptions),\n)\n\n/** The locally selected client which would include code samples from this operation only */\nconst localSelectedClient = ref<ClientOption | CustomClientOption | undefined>(\n findClient(clients.value, selectedClient),\n)\n\n/** If the globally selected client changes we can update the local one */\nwatch(\n () => selectedClient,\n (newClient) => {\n const client = findClient(clients.value, newClient)\n if (client) {\n localSelectedClient.value = client\n }\n },\n)\n\n/** Generate HAR data for webhook requests */\nconst webhookHar = computed(() => {\n if (!isWebhook) return null\n\n try {\n return operationToHar({\n operation,\n method,\n path,\n example: selectedExampleKey.value,\n requestBodyCompositionSelection,\n defaultDisabledParameters: false,\n })\n } catch (error) {\n console.error('[webhookHar]', error)\n return null\n }\n})\n\n/** Generate the code snippet for the selected example */\nconst generatedCode = computed<string>(() => {\n if (isWebhook) {\n return webhookHar.value?.postData?.text ?? ''\n }\n\n return generateCodeSnippet({\n defaultDisabledParameters: false,\n includeDefaultHeaders: integration === 'client',\n clientId: localSelectedClient.value?.id,\n customCodeSamples: customCodeSamples.value,\n operation,\n method,\n path,\n contentType: selectedContentType,\n server: selectedServer,\n securitySchemes,\n example: selectedExampleKey.value,\n globalCookies,\n requestBodyCompositionSelection,\n })\n})\n\n/** The language for the code block, used for syntax highlighting */\nconst codeBlockLanguage = computed(() => {\n if (isWebhook) {\n return webhookLanguage.value\n }\n\n return localSelectedClient.value?.lang\n})\n\n/** Determine the language for webhook content based on MIME type */\nconst webhookLanguage = computed<string>(() => {\n if (!webhookHar.value?.postData) return 'json'\n\n const contentType = webhookHar.value.postData.mimeType\n if (contentType?.includes('json')) return 'json'\n if (contentType?.includes('xml')) return 'xml'\n if (contentType?.includes('yaml') || contentType?.includes('yml'))\n return 'yaml'\n if (contentType?.includes('text/plain')) return 'text'\n\n return 'json'\n})\n\n/** Block secrets from being shown in the code block */\nconst secretCredentials = computed(() => getSecrets(securitySchemes))\n\n/** Grab the ref to freeze the ui as the clients change so there's no jump as the size of the dom changes */\nconst elem = ref<ComponentPublicInstance | null>(null)\n\n/** Set custom example, or update the selected HTTP client globally */\nconst selectClient = (option: ClientOption) => {\n // We need to freeze the ui to prevent scrolling as the clients change\n if (elem.value) {\n const unfreeze = freezeElement(elem.value.$el)\n setTimeout(() => {\n unfreeze()\n }, 300)\n }\n // Update to the local example\n localSelectedClient.value = option\n\n // Emit the change if it's not a custom example\n if (option && !option.id.startsWith('custom')) {\n eventBus.emit('workspace:update:selected-client', option.id)\n }\n}\n\n// Virtualize the code block if it's too large\n// This prevents the entire app from freezing up if there's a massive example\n// We set a lower threshold here as code examples can get quite large\nconst VIRTUALIZATION_THRESHOLD = 20_000\n\nconst shouldVirtualize = computed(\n () => (generatedCode.value.length ?? 0) > VIRTUALIZATION_THRESHOLD,\n)\n\nconst id = useId()\n</script>\n<template>\n <ScalarCard\n v-if=\"generatedCode\"\n ref=\"elem\"\n class=\"request-card dark-mode\">\n <!-- Header -->\n <ScalarCardHeader class=\"pr-2.5\">\n <span class=\"sr-only\">Request Example for</span>\n <HttpMethod\n as=\"span\"\n class=\"request-method\"\n :method=\"method\" />\n <span\n v-if=\"generateLabel\"\n v-html=\"generateLabel()\" />\n <slot name=\"header\" />\n <!-- Client picker -->\n <template\n v-if=\"!isWebhook && clients.length\"\n #actions>\n <ScalarCombobox\n class=\"max-h-80\"\n :filterFn=\"filterClientsByQuery\"\n :modelValue=\"localSelectedClient\"\n :options=\"clients\"\n placement=\"bottom-end\"\n teleport\n @update:modelValue=\"selectClient($event as ClientOption)\">\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex h-full w-fit gap-1.5 px-0.5 py-0 text-base font-normal\"\n data-testid=\"client-picker\"\n variant=\"ghost\">\n {{ localSelectedClient?.title }}\n <ScalarIconCaretDown\n class=\"ui-open:rotate-180 mt-px size-3 transition-transform duration-100\"\n weight=\"bold\" />\n </ScalarButton>\n </ScalarCombobox>\n </template>\n </ScalarCardHeader>\n\n <!-- Code snippet -->\n <ScalarCardSection class=\"request-editor-section custom-scroll p-0\">\n <div\n :id=\"`${id}-example`\"\n class=\"code-snippet\">\n <ScalarCodeBlock\n v-if=\"!shouldVirtualize\"\n class=\"bg-b-2 h-full\"\n :content=\"generatedCode\"\n :hideCredentials=\"secretCredentials\"\n :lang=\"codeBlockLanguage\"\n lineNumbers />\n <ScalarVirtualText\n v-else\n containerClass=\"custom-scroll scalar-code-block border rounded-b flex flex-1 max-h-screen\"\n contentClass=\"language-plaintext whitespace-pre font-code text-base\"\n :lineHeight=\"20\"\n :text=\"generatedCode\" />\n </div>\n </ScalarCardSection>\n\n <!-- Footer -->\n <ScalarCardFooter\n v-if=\"Object.keys(requestBodyExamples).length > 1 || $slots.footer\"\n class=\"request-card-footer bg-b-3\">\n <!-- Example picker -->\n <div\n v-if=\"Object.keys(requestBodyExamples).length > 1\"\n class=\"request-card-footer-addon\">\n <template v-if=\"Object.keys(requestBodyExamples).length\">\n <ExamplePicker\n v-model=\"selectedExampleKey\"\n :examples=\"requestBodyExamples\" />\n </template>\n </div>\n\n <!-- Footer -->\n <slot\n :exampleName=\"selectedExampleKey\"\n name=\"footer\" />\n </ScalarCardFooter>\n </ScalarCard>\n\n <!-- Fallback card with just method and path in the case of no examples -->\n <ScalarCard\n v-else-if=\"fallback\"\n class=\"request-card dark-mode\">\n <ScalarCardSection class=\"request-card-simple\">\n <div class=\"request-header\">\n <HttpMethod\n as=\"span\"\n class=\"request-method\"\n :method=\"method\" />\n <slot name=\"header\" />\n </div>\n <slot\n :exampleName=\"selectedExampleKey\"\n name=\"footer\" />\n </ScalarCardSection>\n </ScalarCard>\n</template>\n<style scoped>\n.request-card {\n font-size: var(--scalar-font-size-3);\n}\n.request-method {\n font-family: var(--scalar-font-code);\n text-transform: uppercase;\n margin-right: 6px;\n}\n.request-card-footer {\n display: flex;\n justify-content: flex-end;\n padding: 6px;\n flex-shrink: 0;\n position: relative;\n}\n.request-card-footer-addon {\n display: flex;\n align-items: center;\n\n flex: 1;\n min-width: 0;\n}\n.request-editor-section {\n display: flex;\n flex: 1;\n}\n.request-card-simple {\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n padding: 8px 8px 8px 12px;\n\n font-size: var(--scalar-small);\n}\n.code-snippet {\n display: flex;\n flex-direction: column;\n width: 100%;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuLA,MAAM,sBAAsB,eAAe;GACzC,MAAM,UAAU,eAAe,QAAA,UAAU,YAAY,EAAE,WAAW,EAAC;GACnE,MAAM,cAAc,QAAA,uBAAuB,OAAO,KAAK,QAAQ,CAAC;AAChE,OAAI,CAAC,YAAa,QAAO,EAAC;AAI1B,UAFiB,QAAQ,cAAc,YAAY,EAAC;IAGrD;;EAGD,MAAM,qBAAqB,SAAmB,SAAC,kBAE9C;AAGD,sBAAoB;AAClB,sBAAmB,UAAU,OAAO,KAAK,oBAAoB,MAAM,CAAC,MAAM;IAC3E;;AAGD,cACQ,QAAA,2BACA;AACJ,OACE,CAAC,OAAO,KAAK,oBAAoB,MAAM,CAAC,SAAS,mBAAmB,MAAK,CAEzE,oBAAmB,QAAQ,OAAO,KAAK,oBAAoB,MAAM,CAAC,MAAM;IAG9E;;EAGA,MAAM,oBAAoB,eAAe,qBAAqB,QAAA,UAAU,CAAA;;EAGxE,MAAM,UAAU,eACd,WAAW,kBAAkB,OAAO,QAAA,cAAc,CACpD;;EAGA,MAAM,sBAAsB,IAC1B,WAAW,QAAQ,OAAO,QAAA,eAAe,CAC3C;;AAGA,cACQ,QAAA,iBACL,cAAc;GACb,MAAM,SAAS,WAAW,QAAQ,OAAO,UAAS;AAClD,OAAI,OACF,qBAAoB,QAAQ;IAGlC;;EAGA,MAAM,aAAa,eAAe;AAChC,OAAI,CAAC,QAAA,UAAW,QAAO;AAEvB,OAAI;AACF,WAAO,eAAe;KACpB,WAAQ,QAAA;KACR,QAAK,QAAA;KACL,MAAG,QAAA;KACH,SAAS,mBAAmB;KAC5B,iCAA8B,QAAA;KAC9B,2BAA2B;KAC5B,CAAA;YACM,OAAO;AACd,YAAQ,MAAM,gBAAgB,MAAK;AACnC,WAAO;;IAEV;;EAGD,MAAM,gBAAgB,eAAuB;AAC3C,OAAI,QAAA,UACF,QAAO,WAAW,OAAO,UAAU,QAAQ;AAG7C,UAAO,oBAAoB;IACzB,2BAA2B;IAC3B,uBAAuB,QAAA,gBAAgB;IACvC,UAAU,oBAAoB,OAAO;IACrC,mBAAmB,kBAAkB;IACrC,WAAQ,QAAA;IACR,QAAK,QAAA;IACL,MAAG,QAAA;IACH,aAAa,QAAA;IACb,QAAQ,QAAA;IACR,iBAAc,QAAA;IACd,SAAS,mBAAmB;IAC5B,eAAY,QAAA;IACZ,iCAA8B,QAAA;IAC/B,CAAA;IACF;;EAGD,MAAM,oBAAoB,eAAe;AACvC,OAAI,QAAA,UACF,QAAO,gBAAgB;AAGzB,UAAO,oBAAoB,OAAO;IACnC;;EAGD,MAAM,kBAAkB,eAAuB;AAC7C,OAAI,CAAC,WAAW,OAAO,SAAU,QAAO;GAExC,MAAM,cAAc,WAAW,MAAM,SAAS;AAC9C,OAAI,aAAa,SAAS,OAAO,CAAE,QAAO;AAC1C,OAAI,aAAa,SAAS,MAAM,CAAE,QAAO;AACzC,OAAI,aAAa,SAAS,OAAO,IAAI,aAAa,SAAS,MAAM,CAC/D,QAAO;AACT,OAAI,aAAa,SAAS,aAAa,CAAE,QAAO;AAEhD,UAAO;IACR;;EAGD,MAAM,oBAAoB,eAAe,WAAW,QAAA,gBAAgB,CAAA;;EAGpE,MAAM,OAAO,IAAoC,KAAI;;EAGrD,MAAM,gBAAgB,WAAyB;AAE7C,OAAI,KAAK,OAAO;IACd,MAAM,WAAW,cAAc,KAAK,MAAM,IAAG;AAC7C,qBAAiB;AACf,eAAS;OACR,IAAG;;AAGR,uBAAoB,QAAQ;AAG5B,OAAI,UAAU,CAAC,OAAO,GAAG,WAAW,SAAS,CAC3C,SAAA,SAAS,KAAK,oCAAoC,OAAO,GAAE;;EAO/D,MAAM,2BAA2B;EAEjC,MAAM,mBAAmB,gBAChB,cAAc,MAAM,UAAU,KAAK,yBAC5C;EAEA,MAAM,KAAK,OAAM;;UAIP,cAAA,SAAA,WAAA,EADR,YAiFa,MAAA,WAAA,EAAA;;aA/EP;IAAJ,KAAI;IACJ,OAAM;;2BAmCa;KAjCnB,YAiCmB,MAAA,iBAAA,EAAA,EAjCD,OAAM,UAAQ,EAAA,YAAA;6BACkB;iCAAhD,mBAAgD,QAAA,EAA1C,OAAM,WAAS,EAAC,uBAAmB,GAAA;OACzC,YAGqB,oBAAA;QAFnB,IAAG;QACH,OAAM;QACL,QAAQ,QAAA;;OAEH,QAAA,iBAAA,WAAA,EADR,mBAE6B,QAAA;;QAA3B,WAAQ,QAAA,eAAa;;OACvB,WAAsB,KAAA,QAAA,UAAA,EAAA,EAAA,KAAA,GAAA,KAAA;;;UAGb,QAAA,aAAa,QAAA,MAAQ,SAAA;YAC3B;wBAkBgB,CAjBjB,YAiBiB,MAAA,eAAA,EAAA;OAhBf,OAAM;OACL,UAAU,MAAA,qBAAoB;OAC9B,YAAY,oBAAA;OACZ,SAAS,QAAA;OACV,WAAU;OACV,UAAA;OACC,uBAAiB,OAAA,OAAA,OAAA,MAAA,WAAE,aAAa,OAAM;;8BASxB,CARf,YAQe,MAAA,aAAA,EAAA;QAPb,OAAM;QACN,eAAY;QACZ,SAAQ;;+BACwB,CAAA,gBAAA,gBAA7B,oBAAA,OAAqB,MAAK,GAAG,KAChC,EAAA,EAAA,YAEkB,MAAA,oBAAA,EAAA;SADhB,OAAM;SACN,QAAO;;;;;;;;;;;;KAOjB,YAkBoB,MAAA,kBAAA,EAAA,EAlBD,OAAM,4CAA0C,EAAA;6BAiB3D,CAhBN,mBAgBM,OAAA;OAfH,IAAE,GAAK,MAAA,GAAE,CAAA;OACV,OAAM;WAEG,iBAAA,SAAA,WAAA,EADT,YAMgB,MAAA,gBAAA,EAAA;;OAJd,OAAM;OACL,SAAS,cAAA;OACT,iBAAiB,kBAAA;OACjB,MAAM,kBAAA;OACP,aAAA;;;;;0BACF,YAK0B,MAAA,kBAAA,EAAA;;OAHxB,gBAAe;OACf,cAAa;OACZ,YAAY;OACZ,MAAM,cAAA;;;;KAML,OAAO,KAAK,oBAAA,MAAmB,CAAE,SAAM,KAAQA,KAAAA,OAAO,UAAA,WAAA,EAD9D,YAkBmB,MAAA,iBAAA,EAAA;;MAhBjB,OAAM;;6BAUA,CAPE,OAAO,KAAK,oBAAA,MAAmB,CAAE,SAAM,KAAA,WAAA,EAD/C,mBAQM,OARN,YAQM,CALY,OAAO,KAAK,oBAAA,MAAmB,CAAE,UAAA,WAAA,EAC/C,YAEoC,uBAAA;;mBADzB,mBAAA;uFAAkB,QAAA;OAC1B,UAAU,oBAAA;iHAKjB,WAEkB,KAAA,QAAA,UAAA,EADf,aAAa,mBAAA,OAAkB,EAAA,KAAA,GAAA,KAAA,CAAA,CAAA;;;;;cAOzB,QAAA,YAAA,WAAA,EADb,YAea,MAAA,WAAA,EAAA;;IAbX,OAAM;;2BAYc,CAXpB,YAWoB,MAAA,kBAAA,EAAA,EAXD,OAAM,uBAAqB,EAAA;4BAOtC,CANN,mBAMM,OANN,YAMM,CALJ,YAGqB,oBAAA;MAFnB,IAAG;MACH,OAAM;MACL,QAAQ,QAAA;8BACX,WAAsB,KAAA,QAAA,UAAA,EAAA,EAAA,KAAA,GAAA,KAAA,CAAA,CAAA,EAExB,WAEkB,KAAA,QAAA,UAAA,EADf,aAAa,mBAAA,OAAkB,EAAA,KAAA,GAAA,KAAA,CAAA,CAAA"}

@@ -1,1 +0,1 @@

{"version":3,"file":"RequestBody.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/request-block/components/RequestBody.vue"],"names":[],"mappings":"AAwSA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2EAA2E,CAAA;AACnH,OAAO,KAAK,EACV,iBAAiB,EAElB,MAAM,8DAA8D,CAAA;AAcrE,KAAK,WAAW,GAAG;IACjB,mBAAmB;IACnB,WAAW,CAAC,EAAE,iBAAiB,CAAA;IAC/B,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAA;IAClB,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,2BAA2B;IAC3B,WAAW,EAAE,kBAAkB,CAAA;IAC/B,sEAAsE;IACtE,+BAA+B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACzD,CAAC;AAigBF,QAAA,MAAM,YAAY;;;;;;;;;;;eAtf4B,MAAM;;;;;;;;;;;;;;;;;;eAAN,MAAM;;;;;;;kFAyflD,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
{"version":3,"file":"RequestBody.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/request-block/components/RequestBody.vue"],"names":[],"mappings":"AAySA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2EAA2E,CAAA;AACnH,OAAO,KAAK,EACV,iBAAiB,EAElB,MAAM,8DAA8D,CAAA;AAcrE,KAAK,WAAW,GAAG;IACjB,mBAAmB;IACnB,WAAW,CAAC,EAAE,iBAAiB,CAAA;IAC/B,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAA;IAClB,oBAAoB;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,2BAA2B;IAC3B,WAAW,EAAE,kBAAkB,CAAA;IAC/B,sEAAsE;IACtE,+BAA+B,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACzD,CAAC;AAmgBF,QAAA,MAAM,YAAY;;;;;;;;;;;eAxf4B,MAAM;;;;;;;;;;;;;;;;;;eAAN,MAAM;;;;;;;kFA2flD,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}

@@ -5,3 +5,3 @@ import _plugin_vue_export_helper_default from "../../../../_virtual/_plugin-vue_export-helper.js";

//#region src/v2/blocks/request-block/components/RequestBody.vue
var RequestBody_default = /* @__PURE__ */ _plugin_vue_export_helper_default(RequestBody_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-e861924b"]]);
var RequestBody_default = /* @__PURE__ */ _plugin_vue_export_helper_default(RequestBody_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-06778e40"]]);
//#endregion

@@ -8,0 +8,0 @@ export { RequestBody_default as default };

@@ -1,1 +0,1 @@

{"version":3,"file":"RequestBody.vue.js","names":[],"sources":["../../../../../src/v2/blocks/request-block/components/RequestBody.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton, ScalarIcon, ScalarListbox } from '@scalar/components'\nimport { CONTENT_TYPES } from '@scalar/helpers/http/content-types'\nimport { objectEntries } from '@scalar/helpers/object/object-entries'\nimport type { ApiReferenceEvents } from '@scalar/workspace-store/events'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport {\n getExampleFromBody,\n getSelectedBodyContentType,\n} from '@scalar/workspace-store/request-example'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type {\n RequestBodyObject,\n SchemaObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed } from 'vue'\n\nimport { useFileDialog } from '@/hooks/use-file-dialog'\nimport RequestBodyForm from '@/v2/blocks/request-block/components/RequestBodyForm.vue'\nimport { getFileName } from '@/v2/blocks/request-block/helpers/files'\nimport { CodeInput } from '@/v2/components/code-input'\nimport {\n DataTable,\n DataTableHeader,\n DataTableRow,\n} from '@/v2/components/data-table'\nimport { CollapsibleSection } from '@/v2/components/layout'\n\nconst {\n requestBody,\n exampleKey,\n environment,\n requestBodyCompositionSelection,\n title,\n} = defineProps<{\n /** Request body */\n requestBody?: RequestBodyObject\n /** Currently selected example key for the current operation */\n exampleKey: string\n /** Display title */\n title: string\n /** Selected environment */\n environment: XScalarEnvironment\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection?: Record<string, number>\n}>()\n\nconst emits = defineEmits<{\n (e: 'update:contentType', payload: { value: string }): void\n /** We use this event to update raw values */\n (\n e: 'update:value',\n payload: Pick<\n ApiReferenceEvents['operation:update:requestBody:value'],\n 'payload' | 'contentType'\n >,\n ): void\n /** We use this event when updating form data only */\n (\n e: 'update:formValue',\n payload: Pick<\n ApiReferenceEvents['operation:update:requestBody:formValue'],\n 'payload' | 'contentType'\n >,\n ): void\n}>()\n\n// Map a content type to a language for the code editor\nconst contentTypeToLanguageMap = {\n 'application/json': 'json',\n 'application/xml': 'xml',\n 'application/yaml': 'yaml',\n} as const\n\n/** Selected content type with default */\nconst selectedContentType = computed(\n () => getSelectedBodyContentType(requestBody, exampleKey) ?? 'none',\n)\n\n/** Convert content types to options for the dropdown */\nconst contentTypeOptions = objectEntries(CONTENT_TYPES).map(([id, label]) => ({\n id,\n label,\n}))\n\nconst selectedContentTypeModel = computed<{ id: string; label: string }>({\n get: () => {\n const found = contentTypeOptions.find(\n (it) => it.id === selectedContentType.value,\n )\n return found ?? contentTypeOptions.at(-1)!\n },\n set: (v) => {\n emits('update:contentType', { value: v.id })\n },\n})\n\nfunction handleFileUpload(callback: (file: File) => void) {\n const { open } = useFileDialog({\n onChange: (files) => {\n const file = files?.[0]\n if (file) {\n callback(file)\n }\n },\n multiple: false,\n accept: '*/*',\n })\n open()\n}\n\n/** Dereferenced example */\nconst example = computed(\n () =>\n requestBody &&\n getExampleFromBody(\n requestBody,\n selectedContentType.value,\n exampleKey,\n requestBodyCompositionSelection,\n ),\n)\n\n/** Convert the example value to a string for the code editor */\nconst bodyValue = computed(() => {\n if (!example.value) {\n return ''\n }\n\n const value = example.value.value\n if (typeof value === 'string') {\n return value\n }\n\n return JSON.stringify(value, null, 2)\n})\n\n/** Resolved schema for the request body */\nconst bodySchema = computed<SchemaObject | undefined>(() => {\n return resolve.schema(\n requestBody?.content?.[selectedContentType.value]?.schema,\n )\n})\n</script>\n<template>\n <CollapsibleSection>\n <template #title>{{ title }}</template>\n <DataTable\n :columns=\"['']\"\n presentational>\n <DataTableHeader\n class=\"relative col-span-full flex h-8 cursor-pointer items-center justify-between border-r-0 !p-0\">\n <ScalarListbox\n v-model=\"selectedContentTypeModel\"\n :options=\"contentTypeOptions\"\n teleport>\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex h-full w-fit gap-1.5 px-3 font-normal\"\n fullWidth\n variant=\"ghost\">\n <span>{{\n CONTENT_TYPES[\n selectedContentType as keyof typeof CONTENT_TYPES\n ] ?? selectedContentType\n }}</span>\n <ScalarIcon\n icon=\"ChevronDown\"\n size=\"md\" />\n </ScalarButton>\n </ScalarListbox>\n </DataTableHeader>\n <DataTableRow>\n <!-- No Body -->\n <template v-if=\"selectedContentType === 'none'\">\n <div\n class=\"text-c-3 flex min-h-10 w-full items-center justify-center border-t p-2 text-sm\">\n <span>No Body</span>\n </div>\n </template>\n\n <!-- Binary File -->\n <template\n v-else-if=\"selectedContentType === 'application/octet-stream'\">\n <div\n class=\"flex items-center justify-center overflow-hidden border-t p-1.5\">\n <template\n v-if=\"\n getFileName(unpackProxyObject(example?.value)) !== undefined\n \">\n <span\n class=\"text-c-2 w-full max-w-full overflow-hidden rounded border px-1.5 py-1 text-xs whitespace-nowrap\">\n {{ getFileName(unpackProxyObject(example?.value)) }}\n </span>\n <ScalarButton\n class=\"bg-b-2 hover:bg-b-3 text-c-2 ml-1 border-0 shadow-none\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"\n emits('update:value', {\n payload: undefined,\n contentType: selectedContentType,\n })\n \">\n Delete\n </ScalarButton>\n </template>\n <template v-else>\n <ScalarButton\n class=\"bg-b-2 hover:bg-b-3 text-c-2 border-0 shadow-none\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"\n () =>\n handleFileUpload((file) =>\n emits('update:value', {\n payload: file,\n contentType: selectedContentType,\n }),\n )\n \">\n <span>Select File</span>\n <ScalarIcon\n class=\"ml-1\"\n icon=\"Upload\"\n size=\"xs\"\n thickness=\"2.5\" />\n </ScalarButton>\n </template>\n </div>\n </template>\n\n <!-- Form Data / URL Encoded -->\n <template\n v-else-if=\"\n selectedContentType === 'multipart/form-data' ||\n selectedContentType === 'application/x-www-form-urlencoded'\n \">\n <RequestBodyForm\n :bodySchema\n :environment\n :example\n :selectedContentType\n @update:formValue=\"\n (payload) =>\n emits('update:formValue', {\n payload,\n contentType: selectedContentType,\n })\n \" />\n </template>\n\n <!-- Code/Other -->\n <template v-else>\n <CodeInput\n class=\"border-t px-3\"\n content=\"\"\n :environment=\"environment\"\n :language=\"\n contentTypeToLanguageMap[\n selectedContentType as keyof typeof contentTypeToLanguageMap\n ] ?? 'plaintext'\n \"\n lineNumbers\n lint\n :modelValue=\"bodyValue\"\n @update:modelValue=\"\n (value) =>\n emits('update:value', {\n payload: value,\n contentType: selectedContentType,\n })\n \" />\n </template>\n </DataTableRow>\n </DataTable>\n </CollapsibleSection>\n</template>\n<style scoped>\n:deep(.cm-content) {\n font-size: var(--scalar-small);\n}\n</style>\n"],"mappings":""}
{"version":3,"file":"RequestBody.vue.js","names":[],"sources":["../../../../../src/v2/blocks/request-block/components/RequestBody.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton, ScalarIcon, ScalarListbox } from '@scalar/components'\nimport { CONTENT_TYPES } from '@scalar/helpers/http/content-types'\nimport { objectEntries } from '@scalar/helpers/object/object-entries'\nimport type { ApiReferenceEvents } from '@scalar/workspace-store/events'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport {\n getExampleFromBody,\n getSelectedBodyContentType,\n} from '@scalar/workspace-store/request-example'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type {\n RequestBodyObject,\n SchemaObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed } from 'vue'\n\nimport { useFileDialog } from '@/hooks/use-file-dialog'\nimport RequestBodyForm from '@/v2/blocks/request-block/components/RequestBodyForm.vue'\nimport { getFileName } from '@/v2/blocks/request-block/helpers/files'\nimport { CodeInput } from '@/v2/components/code-input'\nimport {\n DataTable,\n DataTableHeader,\n DataTableRow,\n} from '@/v2/components/data-table'\nimport { CollapsibleSection } from '@/v2/components/layout'\n\nconst {\n requestBody,\n exampleKey,\n environment,\n requestBodyCompositionSelection,\n title,\n} = defineProps<{\n /** Request body */\n requestBody?: RequestBodyObject\n /** Currently selected example key for the current operation */\n exampleKey: string\n /** Display title */\n title: string\n /** Selected environment */\n environment: XScalarEnvironment\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection?: Record<string, number>\n}>()\n\nconst emits = defineEmits<{\n (e: 'update:contentType', payload: { value: string }): void\n /** We use this event to update raw values */\n (\n e: 'update:value',\n payload: Pick<\n ApiReferenceEvents['operation:update:requestBody:value'],\n 'payload' | 'contentType'\n >,\n ): void\n /** We use this event when updating form data only */\n (\n e: 'update:formValue',\n payload: Pick<\n ApiReferenceEvents['operation:update:requestBody:formValue'],\n 'payload' | 'contentType'\n >,\n ): void\n}>()\n\n// Map a content type to a language for the code editor\nconst contentTypeToLanguageMap = {\n 'application/json': 'json',\n 'application/xml': 'xml',\n 'application/yaml': 'yaml',\n} as const\n\n/** Selected content type with default */\nconst selectedContentType = computed(\n () => getSelectedBodyContentType(requestBody, exampleKey) ?? 'none',\n)\n\n/** Convert content types to options for the dropdown */\nconst contentTypeOptions = objectEntries(CONTENT_TYPES).map(([id, label]) => ({\n id,\n label,\n}))\n\nconst selectedContentTypeModel = computed<{ id: string; label: string }>({\n get: () => {\n const found = contentTypeOptions.find(\n (it) => it.id === selectedContentType.value,\n )\n return found ?? contentTypeOptions.at(-1)!\n },\n set: (v) => {\n emits('update:contentType', { value: v.id })\n },\n})\n\nfunction handleFileUpload(callback: (file: File) => void) {\n const { open } = useFileDialog({\n onChange: (files) => {\n const file = files?.[0]\n if (file) {\n callback(file)\n }\n },\n multiple: false,\n accept: '*/*',\n })\n open()\n}\n\n/** Dereferenced example */\nconst example = computed(\n () =>\n requestBody &&\n getExampleFromBody(\n requestBody,\n selectedContentType.value,\n exampleKey,\n requestBodyCompositionSelection,\n ),\n)\n\n/** Convert the example value to a string for the code editor */\nconst bodyValue = computed(() => {\n if (!example.value) {\n return ''\n }\n\n const value = example.value.value\n if (typeof value === 'string') {\n return value\n }\n\n return JSON.stringify(value, null, 2)\n})\n\n/** Resolved schema for the request body */\nconst bodySchema = computed<SchemaObject | undefined>(() => {\n return resolve.schema(\n requestBody?.content?.[selectedContentType.value]?.schema,\n )\n})\n</script>\n<template>\n <CollapsibleSection>\n <template #title>{{ title }}</template>\n <DataTable\n :columns=\"['']\"\n presentational>\n <DataTableHeader\n class=\"relative col-span-full flex h-8 cursor-pointer items-center justify-between border-r-0 !p-0\">\n <ScalarListbox\n v-model=\"selectedContentTypeModel\"\n :options=\"contentTypeOptions\"\n teleport>\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex h-full w-fit gap-1.5 px-3 font-normal\"\n fullWidth\n variant=\"ghost\">\n <span>{{\n CONTENT_TYPES[\n selectedContentType as keyof typeof CONTENT_TYPES\n ] ?? selectedContentType\n }}</span>\n <ScalarIcon\n icon=\"ChevronDown\"\n size=\"md\" />\n </ScalarButton>\n </ScalarListbox>\n </DataTableHeader>\n <DataTableRow>\n <!-- No Body -->\n <template v-if=\"selectedContentType === 'none'\">\n <div\n class=\"text-c-3 flex min-h-10 w-full items-center justify-center border-t p-2 text-sm\">\n <span>No Body</span>\n </div>\n </template>\n\n <!-- Binary File -->\n <template\n v-else-if=\"selectedContentType === 'application/octet-stream'\">\n <div\n class=\"flex items-center justify-center overflow-hidden border-t p-1.5\">\n <template\n v-if=\"\n getFileName(unpackProxyObject(example?.value)) !== undefined\n \">\n <span\n class=\"text-c-2 w-full max-w-full overflow-hidden rounded border px-1.5 py-1 text-xs whitespace-nowrap\">\n {{ getFileName(unpackProxyObject(example?.value)) }}\n </span>\n <ScalarButton\n class=\"bg-b-2 hover:bg-b-3 text-c-2 ml-1 border-0 shadow-none\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"\n emits('update:value', {\n payload: undefined,\n contentType: selectedContentType,\n })\n \">\n Delete\n </ScalarButton>\n </template>\n <template v-else>\n <ScalarButton\n class=\"bg-b-2 hover:bg-b-3 text-c-2 border-0 shadow-none\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"\n () =>\n handleFileUpload((file) =>\n emits('update:value', {\n payload: file,\n contentType: selectedContentType,\n }),\n )\n \">\n <span>Select File</span>\n <ScalarIcon\n class=\"ml-1\"\n icon=\"Upload\"\n size=\"xs\"\n thickness=\"2.5\" />\n </ScalarButton>\n </template>\n </div>\n </template>\n\n <!-- Form Data / URL Encoded -->\n <template\n v-else-if=\"\n selectedContentType === 'multipart/form-data' ||\n selectedContentType === 'application/x-www-form-urlencoded'\n \">\n <RequestBodyForm\n :bodySchema\n :environment\n :example\n :selectedContentType\n @update:formValue=\"\n (payload) =>\n emits('update:formValue', {\n payload,\n contentType: selectedContentType,\n })\n \" />\n </template>\n\n <!-- Code/Other -->\n <template v-else>\n <CodeInput\n class=\"border-t px-3\"\n content=\"\"\n :environment=\"environment\"\n :language=\"\n contentTypeToLanguageMap[\n selectedContentType as keyof typeof contentTypeToLanguageMap\n ] ?? 'plaintext'\n \"\n lineNumbers\n lint\n :modelValue=\"bodyValue\"\n withFakeData\n @update:modelValue=\"\n (value) =>\n emits('update:value', {\n payload: value,\n contentType: selectedContentType,\n })\n \" />\n </template>\n </DataTableRow>\n </DataTable>\n </CollapsibleSection>\n</template>\n<style scoped>\n:deep(.cm-content) {\n font-size: var(--scalar-small);\n}\n</style>\n"],"mappings":""}

@@ -167,2 +167,3 @@ import { useFileDialog } from "../../../../hooks/use-file-dialog.js";

modelValue: bodyValue.value,
withFakeData: "",
"onUpdate:modelValue": _cache[4] || (_cache[4] = (value) => emits("update:value", {

@@ -169,0 +170,0 @@ payload: value,

@@ -1,1 +0,1 @@

{"version":3,"file":"RequestBody.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/request-block/components/RequestBody.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton, ScalarIcon, ScalarListbox } from '@scalar/components'\nimport { CONTENT_TYPES } from '@scalar/helpers/http/content-types'\nimport { objectEntries } from '@scalar/helpers/object/object-entries'\nimport type { ApiReferenceEvents } from '@scalar/workspace-store/events'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport {\n getExampleFromBody,\n getSelectedBodyContentType,\n} from '@scalar/workspace-store/request-example'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type {\n RequestBodyObject,\n SchemaObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed } from 'vue'\n\nimport { useFileDialog } from '@/hooks/use-file-dialog'\nimport RequestBodyForm from '@/v2/blocks/request-block/components/RequestBodyForm.vue'\nimport { getFileName } from '@/v2/blocks/request-block/helpers/files'\nimport { CodeInput } from '@/v2/components/code-input'\nimport {\n DataTable,\n DataTableHeader,\n DataTableRow,\n} from '@/v2/components/data-table'\nimport { CollapsibleSection } from '@/v2/components/layout'\n\nconst {\n requestBody,\n exampleKey,\n environment,\n requestBodyCompositionSelection,\n title,\n} = defineProps<{\n /** Request body */\n requestBody?: RequestBodyObject\n /** Currently selected example key for the current operation */\n exampleKey: string\n /** Display title */\n title: string\n /** Selected environment */\n environment: XScalarEnvironment\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection?: Record<string, number>\n}>()\n\nconst emits = defineEmits<{\n (e: 'update:contentType', payload: { value: string }): void\n /** We use this event to update raw values */\n (\n e: 'update:value',\n payload: Pick<\n ApiReferenceEvents['operation:update:requestBody:value'],\n 'payload' | 'contentType'\n >,\n ): void\n /** We use this event when updating form data only */\n (\n e: 'update:formValue',\n payload: Pick<\n ApiReferenceEvents['operation:update:requestBody:formValue'],\n 'payload' | 'contentType'\n >,\n ): void\n}>()\n\n// Map a content type to a language for the code editor\nconst contentTypeToLanguageMap = {\n 'application/json': 'json',\n 'application/xml': 'xml',\n 'application/yaml': 'yaml',\n} as const\n\n/** Selected content type with default */\nconst selectedContentType = computed(\n () => getSelectedBodyContentType(requestBody, exampleKey) ?? 'none',\n)\n\n/** Convert content types to options for the dropdown */\nconst contentTypeOptions = objectEntries(CONTENT_TYPES).map(([id, label]) => ({\n id,\n label,\n}))\n\nconst selectedContentTypeModel = computed<{ id: string; label: string }>({\n get: () => {\n const found = contentTypeOptions.find(\n (it) => it.id === selectedContentType.value,\n )\n return found ?? contentTypeOptions.at(-1)!\n },\n set: (v) => {\n emits('update:contentType', { value: v.id })\n },\n})\n\nfunction handleFileUpload(callback: (file: File) => void) {\n const { open } = useFileDialog({\n onChange: (files) => {\n const file = files?.[0]\n if (file) {\n callback(file)\n }\n },\n multiple: false,\n accept: '*/*',\n })\n open()\n}\n\n/** Dereferenced example */\nconst example = computed(\n () =>\n requestBody &&\n getExampleFromBody(\n requestBody,\n selectedContentType.value,\n exampleKey,\n requestBodyCompositionSelection,\n ),\n)\n\n/** Convert the example value to a string for the code editor */\nconst bodyValue = computed(() => {\n if (!example.value) {\n return ''\n }\n\n const value = example.value.value\n if (typeof value === 'string') {\n return value\n }\n\n return JSON.stringify(value, null, 2)\n})\n\n/** Resolved schema for the request body */\nconst bodySchema = computed<SchemaObject | undefined>(() => {\n return resolve.schema(\n requestBody?.content?.[selectedContentType.value]?.schema,\n )\n})\n</script>\n<template>\n <CollapsibleSection>\n <template #title>{{ title }}</template>\n <DataTable\n :columns=\"['']\"\n presentational>\n <DataTableHeader\n class=\"relative col-span-full flex h-8 cursor-pointer items-center justify-between border-r-0 !p-0\">\n <ScalarListbox\n v-model=\"selectedContentTypeModel\"\n :options=\"contentTypeOptions\"\n teleport>\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex h-full w-fit gap-1.5 px-3 font-normal\"\n fullWidth\n variant=\"ghost\">\n <span>{{\n CONTENT_TYPES[\n selectedContentType as keyof typeof CONTENT_TYPES\n ] ?? selectedContentType\n }}</span>\n <ScalarIcon\n icon=\"ChevronDown\"\n size=\"md\" />\n </ScalarButton>\n </ScalarListbox>\n </DataTableHeader>\n <DataTableRow>\n <!-- No Body -->\n <template v-if=\"selectedContentType === 'none'\">\n <div\n class=\"text-c-3 flex min-h-10 w-full items-center justify-center border-t p-2 text-sm\">\n <span>No Body</span>\n </div>\n </template>\n\n <!-- Binary File -->\n <template\n v-else-if=\"selectedContentType === 'application/octet-stream'\">\n <div\n class=\"flex items-center justify-center overflow-hidden border-t p-1.5\">\n <template\n v-if=\"\n getFileName(unpackProxyObject(example?.value)) !== undefined\n \">\n <span\n class=\"text-c-2 w-full max-w-full overflow-hidden rounded border px-1.5 py-1 text-xs whitespace-nowrap\">\n {{ getFileName(unpackProxyObject(example?.value)) }}\n </span>\n <ScalarButton\n class=\"bg-b-2 hover:bg-b-3 text-c-2 ml-1 border-0 shadow-none\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"\n emits('update:value', {\n payload: undefined,\n contentType: selectedContentType,\n })\n \">\n Delete\n </ScalarButton>\n </template>\n <template v-else>\n <ScalarButton\n class=\"bg-b-2 hover:bg-b-3 text-c-2 border-0 shadow-none\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"\n () =>\n handleFileUpload((file) =>\n emits('update:value', {\n payload: file,\n contentType: selectedContentType,\n }),\n )\n \">\n <span>Select File</span>\n <ScalarIcon\n class=\"ml-1\"\n icon=\"Upload\"\n size=\"xs\"\n thickness=\"2.5\" />\n </ScalarButton>\n </template>\n </div>\n </template>\n\n <!-- Form Data / URL Encoded -->\n <template\n v-else-if=\"\n selectedContentType === 'multipart/form-data' ||\n selectedContentType === 'application/x-www-form-urlencoded'\n \">\n <RequestBodyForm\n :bodySchema\n :environment\n :example\n :selectedContentType\n @update:formValue=\"\n (payload) =>\n emits('update:formValue', {\n payload,\n contentType: selectedContentType,\n })\n \" />\n </template>\n\n <!-- Code/Other -->\n <template v-else>\n <CodeInput\n class=\"border-t px-3\"\n content=\"\"\n :environment=\"environment\"\n :language=\"\n contentTypeToLanguageMap[\n selectedContentType as keyof typeof contentTypeToLanguageMap\n ] ?? 'plaintext'\n \"\n lineNumbers\n lint\n :modelValue=\"bodyValue\"\n @update:modelValue=\"\n (value) =>\n emits('update:value', {\n payload: value,\n contentType: selectedContentType,\n })\n \" />\n </template>\n </DataTableRow>\n </DataTable>\n </CollapsibleSection>\n</template>\n<style scoped>\n:deep(.cm-content) {\n font-size: var(--scalar-small);\n}\n</style>\n"],"mappings":"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"}
{"version":3,"file":"RequestBody.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/request-block/components/RequestBody.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton, ScalarIcon, ScalarListbox } from '@scalar/components'\nimport { CONTENT_TYPES } from '@scalar/helpers/http/content-types'\nimport { objectEntries } from '@scalar/helpers/object/object-entries'\nimport type { ApiReferenceEvents } from '@scalar/workspace-store/events'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport {\n getExampleFromBody,\n getSelectedBodyContentType,\n} from '@scalar/workspace-store/request-example'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type {\n RequestBodyObject,\n SchemaObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed } from 'vue'\n\nimport { useFileDialog } from '@/hooks/use-file-dialog'\nimport RequestBodyForm from '@/v2/blocks/request-block/components/RequestBodyForm.vue'\nimport { getFileName } from '@/v2/blocks/request-block/helpers/files'\nimport { CodeInput } from '@/v2/components/code-input'\nimport {\n DataTable,\n DataTableHeader,\n DataTableRow,\n} from '@/v2/components/data-table'\nimport { CollapsibleSection } from '@/v2/components/layout'\n\nconst {\n requestBody,\n exampleKey,\n environment,\n requestBodyCompositionSelection,\n title,\n} = defineProps<{\n /** Request body */\n requestBody?: RequestBodyObject\n /** Currently selected example key for the current operation */\n exampleKey: string\n /** Display title */\n title: string\n /** Selected environment */\n environment: XScalarEnvironment\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection?: Record<string, number>\n}>()\n\nconst emits = defineEmits<{\n (e: 'update:contentType', payload: { value: string }): void\n /** We use this event to update raw values */\n (\n e: 'update:value',\n payload: Pick<\n ApiReferenceEvents['operation:update:requestBody:value'],\n 'payload' | 'contentType'\n >,\n ): void\n /** We use this event when updating form data only */\n (\n e: 'update:formValue',\n payload: Pick<\n ApiReferenceEvents['operation:update:requestBody:formValue'],\n 'payload' | 'contentType'\n >,\n ): void\n}>()\n\n// Map a content type to a language for the code editor\nconst contentTypeToLanguageMap = {\n 'application/json': 'json',\n 'application/xml': 'xml',\n 'application/yaml': 'yaml',\n} as const\n\n/** Selected content type with default */\nconst selectedContentType = computed(\n () => getSelectedBodyContentType(requestBody, exampleKey) ?? 'none',\n)\n\n/** Convert content types to options for the dropdown */\nconst contentTypeOptions = objectEntries(CONTENT_TYPES).map(([id, label]) => ({\n id,\n label,\n}))\n\nconst selectedContentTypeModel = computed<{ id: string; label: string }>({\n get: () => {\n const found = contentTypeOptions.find(\n (it) => it.id === selectedContentType.value,\n )\n return found ?? contentTypeOptions.at(-1)!\n },\n set: (v) => {\n emits('update:contentType', { value: v.id })\n },\n})\n\nfunction handleFileUpload(callback: (file: File) => void) {\n const { open } = useFileDialog({\n onChange: (files) => {\n const file = files?.[0]\n if (file) {\n callback(file)\n }\n },\n multiple: false,\n accept: '*/*',\n })\n open()\n}\n\n/** Dereferenced example */\nconst example = computed(\n () =>\n requestBody &&\n getExampleFromBody(\n requestBody,\n selectedContentType.value,\n exampleKey,\n requestBodyCompositionSelection,\n ),\n)\n\n/** Convert the example value to a string for the code editor */\nconst bodyValue = computed(() => {\n if (!example.value) {\n return ''\n }\n\n const value = example.value.value\n if (typeof value === 'string') {\n return value\n }\n\n return JSON.stringify(value, null, 2)\n})\n\n/** Resolved schema for the request body */\nconst bodySchema = computed<SchemaObject | undefined>(() => {\n return resolve.schema(\n requestBody?.content?.[selectedContentType.value]?.schema,\n )\n})\n</script>\n<template>\n <CollapsibleSection>\n <template #title>{{ title }}</template>\n <DataTable\n :columns=\"['']\"\n presentational>\n <DataTableHeader\n class=\"relative col-span-full flex h-8 cursor-pointer items-center justify-between border-r-0 !p-0\">\n <ScalarListbox\n v-model=\"selectedContentTypeModel\"\n :options=\"contentTypeOptions\"\n teleport>\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex h-full w-fit gap-1.5 px-3 font-normal\"\n fullWidth\n variant=\"ghost\">\n <span>{{\n CONTENT_TYPES[\n selectedContentType as keyof typeof CONTENT_TYPES\n ] ?? selectedContentType\n }}</span>\n <ScalarIcon\n icon=\"ChevronDown\"\n size=\"md\" />\n </ScalarButton>\n </ScalarListbox>\n </DataTableHeader>\n <DataTableRow>\n <!-- No Body -->\n <template v-if=\"selectedContentType === 'none'\">\n <div\n class=\"text-c-3 flex min-h-10 w-full items-center justify-center border-t p-2 text-sm\">\n <span>No Body</span>\n </div>\n </template>\n\n <!-- Binary File -->\n <template\n v-else-if=\"selectedContentType === 'application/octet-stream'\">\n <div\n class=\"flex items-center justify-center overflow-hidden border-t p-1.5\">\n <template\n v-if=\"\n getFileName(unpackProxyObject(example?.value)) !== undefined\n \">\n <span\n class=\"text-c-2 w-full max-w-full overflow-hidden rounded border px-1.5 py-1 text-xs whitespace-nowrap\">\n {{ getFileName(unpackProxyObject(example?.value)) }}\n </span>\n <ScalarButton\n class=\"bg-b-2 hover:bg-b-3 text-c-2 ml-1 border-0 shadow-none\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"\n emits('update:value', {\n payload: undefined,\n contentType: selectedContentType,\n })\n \">\n Delete\n </ScalarButton>\n </template>\n <template v-else>\n <ScalarButton\n class=\"bg-b-2 hover:bg-b-3 text-c-2 border-0 shadow-none\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"\n () =>\n handleFileUpload((file) =>\n emits('update:value', {\n payload: file,\n contentType: selectedContentType,\n }),\n )\n \">\n <span>Select File</span>\n <ScalarIcon\n class=\"ml-1\"\n icon=\"Upload\"\n size=\"xs\"\n thickness=\"2.5\" />\n </ScalarButton>\n </template>\n </div>\n </template>\n\n <!-- Form Data / URL Encoded -->\n <template\n v-else-if=\"\n selectedContentType === 'multipart/form-data' ||\n selectedContentType === 'application/x-www-form-urlencoded'\n \">\n <RequestBodyForm\n :bodySchema\n :environment\n :example\n :selectedContentType\n @update:formValue=\"\n (payload) =>\n emits('update:formValue', {\n payload,\n contentType: selectedContentType,\n })\n \" />\n </template>\n\n <!-- Code/Other -->\n <template v-else>\n <CodeInput\n class=\"border-t px-3\"\n content=\"\"\n :environment=\"environment\"\n :language=\"\n contentTypeToLanguageMap[\n selectedContentType as keyof typeof contentTypeToLanguageMap\n ] ?? 'plaintext'\n \"\n lineNumbers\n lint\n :modelValue=\"bodyValue\"\n withFakeData\n @update:modelValue=\"\n (value) =>\n emits('update:value', {\n payload: value,\n contentType: selectedContentType,\n })\n \" />\n </template>\n </DataTableRow>\n </DataTable>\n </CollapsibleSection>\n</template>\n<style scoped>\n:deep(.cm-content) {\n font-size: var(--scalar-small);\n}\n</style>\n"],"mappings":"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"}

@@ -1,1 +0,1 @@

{"version":3,"file":"RequestTableRow.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/request-block/components/RequestTableRow.vue"],"names":[],"mappings":"AAmTA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AAGxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2EAA2E,CAAA;AACnH,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACb,MAAM,8DAA8D,CAAA;AAcrE,MAAM,MAAM,QAAQ,GAAG;IACrB,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAA;IACZ,0DAA0D;IAC1D,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAA;IAC3B,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mFAAmF;IACnF,WAAW,CAAC,EAAE,kBAAkB,CAAC,aAAa,CAAC,CAAA;IAC/C,iDAAiD;IACjD,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,wEAAwE;IACxE,MAAM,CAAC,EAAE,YAAY,CAAA;IACrB,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,mDAAmD;IACnD,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,uDAAuD;IACvD,iBAAiB,CAAC,EAAE,eAAe,CAAA;CACpC,CAAA;AAED,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,QAAQ,CAAA;IACd,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,kBAAkB,CAAA;IAC/B,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B,CAAC;AAkmBF,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;cArlBG,MAAM;eAAS,MAAM,GAAG,IAAI;oBAAc,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAAjD,MAAM;eAAS,MAAM,GAAG,IAAI;oBAAc,OAAO;;;;;kFAwlBpE,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
{"version":3,"file":"RequestTableRow.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/request-block/components/RequestTableRow.vue"],"names":[],"mappings":"AAoTA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AAGxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2EAA2E,CAAA;AACnH,OAAO,KAAK,EACV,eAAe,EACf,YAAY,EACb,MAAM,8DAA8D,CAAA;AAcrE,MAAM,MAAM,QAAQ,GAAG;IACrB,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAA;IACZ,0DAA0D;IAC1D,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAA;IAC3B,6CAA6C;IAC7C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,mFAAmF;IACnF,WAAW,CAAC,EAAE,kBAAkB,CAAC,aAAa,CAAC,CAAA;IAC/C,iDAAiD;IACjD,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,wEAAwE;IACxE,MAAM,CAAC,EAAE,YAAY,CAAA;IACrB,wCAAwC;IACxC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,mDAAmD;IACnD,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,uDAAuD;IACvD,iBAAiB,CAAC,EAAE,eAAe,CAAA;CACpC,CAAA;AAED,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,QAAQ,CAAA;IACd,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,kBAAkB,CAAA;IAC/B,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B,CAAC;AAomBF,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;cAvlBG,MAAM;eAAS,MAAM,GAAG,IAAI;oBAAc,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAAjD,MAAM;eAAS,MAAM,GAAG,IAAI;oBAAc,OAAO;;;;;kFA0lBpE,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}

@@ -1,1 +0,1 @@

{"version":3,"file":"RequestTableRow.vue.js","names":[],"sources":["../../../../../src/v2/blocks/request-block/components/RequestTableRow.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton, ScalarIcon, ScalarIconButton } from '@scalar/components'\nimport { ScalarIconGlobe, ScalarIconTrash } from '@scalar/icons'\nimport type { ApiReferenceEvents } from '@scalar/workspace-store/events'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type {\n ParameterObject,\n SchemaObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, ref, watch } from 'vue'\n\nimport { getFileName } from '@/v2/blocks/request-block/helpers/files'\nimport { validateParameter } from '@/v2/blocks/request-block/helpers/validate-parameter'\nimport { CodeInput } from '@/v2/components/code-input'\nimport {\n DataTableCell,\n DataTableCheckbox,\n DataTableRow,\n} from '@/v2/components/data-table'\n\nimport RequestTableTooltip from './RequestTableTooltip.vue'\n\nexport type TableRow = {\n /** The parameter or field name/key */\n name: string\n /** The parameter value, can be a string, file, or null */\n value: string | File | null\n /** Optional description for the parameter */\n description?: string\n /** Optional route for global parameters (e.g., cookies shared across workspace) */\n globalRoute?: ApiReferenceEvents['ui:navigate']\n /** Whether the parameter is disabled/inactive */\n isDisabled?: boolean\n /** OpenAPI schema object with type, validation rules, examples, etc. */\n schema?: SchemaObject\n /** Whether the parameter is required */\n isRequired?: boolean\n /**\n * Whether the parameter is readonly and can not be modifies directly\n * User can still override the parameter which is going to show up with the linethrough style\n */\n isReadonly?: boolean\n /** Whether the parameter is overridden later on */\n isOverridden?: boolean\n /** Track the original parameter so we can update it */\n originalParameter?: ParameterObject\n}\n\nconst {\n data,\n environment,\n hasCheckboxDisabled,\n invalidParams,\n showUploadButton,\n} = defineProps<{\n data: TableRow\n hasCheckboxDisabled?: boolean\n invalidParams?: Set<string>\n label?: string\n environment: XScalarEnvironment\n showUploadButton?: boolean\n}>()\n\nconst emit = defineEmits<{\n (\n e: 'upsertRow',\n payload: { name: string; value: string | File; isDisabled: boolean },\n ): void\n (e: 'deleteRow'): void\n (e: 'uploadFile'): void\n (e: 'removeFile'): void\n (e: 'navigate', route: NonNullable<TableRow['globalRoute']>): void\n}>()\n\n/**\n * Track local state for the row\n *\n * Now this is required because of the way we get default values from the schema.\n * If we have a default value in data.value, then we update isDisabled to true. We lose the default value since now\n * we have an example where value: ''. This is why we need to track the local state and update all of the params at the\n * same time.\n */\nconst name = ref<string>(data.name ?? '')\nconst value = ref<string | File>(unpackProxyObject(data.value) ?? '')\nconst isDisabled = ref<boolean>(data.isDisabled ?? false)\n\n// Keep the above state synced with the data prop\nwatch(\n () => data.name,\n (newName) => (name.value = newName ?? ''),\n)\nwatch(\n () => data.value,\n (newValue) => (value.value = unpackProxyObject(newValue) ?? ''),\n)\nwatch(\n () => data.isDisabled,\n (newIsDisabled) => (isDisabled.value = newIsDisabled ?? false),\n)\n\n/** Check if the value is a File instance */\nconst isFile = computed(() => value.value instanceof File)\n\n/** Display value handles File instances and shows filename instead */\nconst displayValue = computed(\n () =>\n (isFile.value\n ? getFileName(value.value as File)\n : (value.value as string)) ?? '',\n)\n\nconst defaultValue = computed(() => data.schema?.default as string)\n\n/** See if we can extract enum values from the schema */\nconst enumValue = computed<string[]>(() => {\n if (!data.schema) {\n return []\n }\n\n // Grab the enum from the schema\n if (data.schema.enum) {\n return data.schema.enum.map((item) => String(item))\n }\n\n // Grab the enum from the items schema\n if ('items' in data.schema) {\n const resolved = resolve.schema(data.schema.items)\n if (resolved?.enum) {\n return resolved.enum.map((item) => String(item))\n }\n }\n\n return []\n})\n\nconst minimumValue = computed(() =>\n data.schema && 'minimum' in data.schema ? data.schema.minimum : undefined,\n)\nconst maximumValue = computed(() =>\n data.schema && 'maximum' in data.schema ? data.schema.maximum : undefined,\n)\nconst typeValue = computed(() =>\n data.schema && 'type' in data.schema ? data.schema.type : undefined,\n)\n\nconst validationResult = computed(() =>\n validateParameter(data.schema, value.value),\n)\n\n/** Handle row updates while preserving existing properties */\nconst handleUpdateRow = (\n payload: Partial<{ name: string; value: string; isDisabled: boolean }>,\n): void => {\n // Update our local state\n if (payload.name !== undefined) {\n name.value = payload.name\n }\n if (payload.value !== undefined) {\n value.value = payload.value\n }\n\n // Is disabled should always be false unless you explicitly set it to true\n isDisabled.value = payload.isDisabled ?? false\n\n // Emit all of the local state\n emit('upsertRow', {\n name: name.value,\n value: value.value,\n isDisabled: isDisabled.value,\n })\n}\n</script>\n\n<template>\n <DataTableRow\n :id=\"data.name\"\n :class=\"{\n alert: validationResult.ok === false,\n error: validationResult.ok === false && invalidParams?.has(data.name),\n }\">\n <DataTableCheckbox\n class=\"!border-r\"\n :disabled=\"hasCheckboxDisabled ?? false\"\n :modelValue=\"!isDisabled\"\n @update:modelValue=\"(v) => handleUpdateRow({ isDisabled: !v })\" />\n\n <!-- Name -->\n <DataTableCell>\n <CodeInput\n :aria-label=\"`${label} Key`\"\n disableCloseBrackets\n :disabled=\"data.isReadonly\"\n disableEnter\n disableTabIndent\n :environment=\"environment\"\n lineWrapping\n :modelValue=\"name\"\n placeholder=\"Key\"\n :required=\"Boolean(data.isRequired)\"\n @navigate=\"(route) => emit('navigate', route)\"\n @selectVariable=\"(v: string) => handleUpdateRow({ name: v })\"\n @update:modelValue=\"(v) => handleUpdateRow({ name: v })\" />\n </DataTableCell>\n\n <!-- Value -->\n <DataTableCell>\n <CodeInput\n :aria-label=\"`${label} Value`\"\n class=\"pr-6 group-hover:pr-10 group-has-[.cm-focused]:pr-10\"\n :default=\"defaultValue\"\n disableCloseBrackets\n :disabled=\"data.isReadonly\"\n disableEnter\n disableTabIndent\n :enum=\"enumValue\"\n :environment=\"environment\"\n :examples=\"\n data.schema?.examples?.map((example) => String(example)) ?? []\n \"\n :linethrough=\"data.isOverridden\"\n lineWrapping\n :max=\"maximumValue\"\n :min=\"minimumValue\"\n :modelValue=\"displayValue\"\n placeholder=\"Value\"\n :type=\"typeValue\"\n @navigate=\"(route) => emit('navigate', route)\"\n @update:modelValue=\"(v) => handleUpdateRow({ value: v })\">\n <template #icon>\n <ScalarButton\n v-if=\"\n Boolean(data.name || value) &&\n !data.isRequired &&\n data.isReadonly !== true\n \"\n class=\"text-c-2 hover:text-c-1 hover:bg-b-2 z-context -mr-0.5 hidden h-fit rounded p-1 group-hover:flex group-has-[.cm-focused]:flex\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"emit('deleteRow')\">\n <ScalarIconTrash class=\"size-3.5\" />\n </ScalarButton>\n\n <ScalarIconButton\n v-if=\"data.globalRoute !== undefined\"\n class=\"text-c-2 hover:text-c-1 hover:bg-b-2 z-context -mr-0.5 h-fit\"\n :icon=\"ScalarIconGlobe\"\n label=\"Global cookies are shared across the whole workspace. Click to navigate.\"\n size=\"xs\"\n tooltip=\"top\"\n variant=\"ghost\"\n @click=\"emit('navigate', data.globalRoute)\" />\n\n <RequestTableTooltip\n v-if=\"data.isReadonly\"\n description=\"This is a readonly property and you can not modify it! If you want to change it you have to override it or disable it using the checkbox\"\n :value=\"null\" />\n <RequestTableTooltip\n v-else-if=\"data.schema\"\n :description=\"data.description\"\n :schema=\"data.schema\"\n :value />\n </template>\n </CodeInput>\n </DataTableCell>\n\n <!-- File upload -->\n <DataTableCell\n v-if=\"showUploadButton\"\n class=\"group/upload flex items-center justify-center whitespace-nowrap\">\n <template v-if=\"isFile\">\n <div\n class=\"text-c-2 filemask flex w-full max-w-[100%] items-center justify-center overflow-hidden p-1\">\n <span>{{ displayValue }}</span>\n </div>\n <button\n class=\"bg-b-2 mt-1 block rounded p-0.5 text-center text-xs font-medium md:pointer-events-none md:absolute md:inset-x-1 md:top-1/2 md:mt-0 md:-translate-y-1/2 md:opacity-0 md:group-hover/upload:pointer-events-auto md:group-hover/upload:opacity-100\"\n type=\"button\"\n @click=\"emit('removeFile')\">\n Delete\n </button>\n </template>\n <template v-else>\n <div class=\"p-0.5\">\n <ScalarButton\n class=\"bg-b-2 hover:bg-b-3 text-c-2 h-fit border-0 py-px shadow-none\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"emit('uploadFile')\">\n <span>Select File</span>\n <ScalarIcon\n class=\"ml-1\"\n icon=\"Upload\"\n size=\"xs\"\n thickness=\"2.5\" />\n </ScalarButton>\n </div>\n </template>\n </DataTableCell>\n </DataTableRow>\n</template>\n"],"mappings":""}
{"version":3,"file":"RequestTableRow.vue.js","names":[],"sources":["../../../../../src/v2/blocks/request-block/components/RequestTableRow.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton, ScalarIcon, ScalarIconButton } from '@scalar/components'\nimport { ScalarIconGlobe, ScalarIconTrash } from '@scalar/icons'\nimport type { ApiReferenceEvents } from '@scalar/workspace-store/events'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type {\n ParameterObject,\n SchemaObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, ref, watch } from 'vue'\n\nimport { getFileName } from '@/v2/blocks/request-block/helpers/files'\nimport { validateParameter } from '@/v2/blocks/request-block/helpers/validate-parameter'\nimport { CodeInput } from '@/v2/components/code-input'\nimport {\n DataTableCell,\n DataTableCheckbox,\n DataTableRow,\n} from '@/v2/components/data-table'\n\nimport RequestTableTooltip from './RequestTableTooltip.vue'\n\nexport type TableRow = {\n /** The parameter or field name/key */\n name: string\n /** The parameter value, can be a string, file, or null */\n value: string | File | null\n /** Optional description for the parameter */\n description?: string\n /** Optional route for global parameters (e.g., cookies shared across workspace) */\n globalRoute?: ApiReferenceEvents['ui:navigate']\n /** Whether the parameter is disabled/inactive */\n isDisabled?: boolean\n /** OpenAPI schema object with type, validation rules, examples, etc. */\n schema?: SchemaObject\n /** Whether the parameter is required */\n isRequired?: boolean\n /**\n * Whether the parameter is readonly and can not be modifies directly\n * User can still override the parameter which is going to show up with the linethrough style\n */\n isReadonly?: boolean\n /** Whether the parameter is overridden later on */\n isOverridden?: boolean\n /** Track the original parameter so we can update it */\n originalParameter?: ParameterObject\n}\n\nconst {\n data,\n environment,\n hasCheckboxDisabled,\n invalidParams,\n showUploadButton,\n} = defineProps<{\n data: TableRow\n hasCheckboxDisabled?: boolean\n invalidParams?: Set<string>\n label?: string\n environment: XScalarEnvironment\n showUploadButton?: boolean\n}>()\n\nconst emit = defineEmits<{\n (\n e: 'upsertRow',\n payload: { name: string; value: string | File; isDisabled: boolean },\n ): void\n (e: 'deleteRow'): void\n (e: 'uploadFile'): void\n (e: 'removeFile'): void\n (e: 'navigate', route: NonNullable<TableRow['globalRoute']>): void\n}>()\n\n/**\n * Track local state for the row\n *\n * Now this is required because of the way we get default values from the schema.\n * If we have a default value in data.value, then we update isDisabled to true. We lose the default value since now\n * we have an example where value: ''. This is why we need to track the local state and update all of the params at the\n * same time.\n */\nconst name = ref<string>(data.name ?? '')\nconst value = ref<string | File>(unpackProxyObject(data.value) ?? '')\nconst isDisabled = ref<boolean>(data.isDisabled ?? false)\n\n// Keep the above state synced with the data prop\nwatch(\n () => data.name,\n (newName) => (name.value = newName ?? ''),\n)\nwatch(\n () => data.value,\n (newValue) => (value.value = unpackProxyObject(newValue) ?? ''),\n)\nwatch(\n () => data.isDisabled,\n (newIsDisabled) => (isDisabled.value = newIsDisabled ?? false),\n)\n\n/** Check if the value is a File instance */\nconst isFile = computed(() => value.value instanceof File)\n\n/** Display value handles File instances and shows filename instead */\nconst displayValue = computed(\n () =>\n (isFile.value\n ? getFileName(value.value as File)\n : (value.value as string)) ?? '',\n)\n\nconst defaultValue = computed(() => data.schema?.default as string)\n\n/** See if we can extract enum values from the schema */\nconst enumValue = computed<string[]>(() => {\n if (!data.schema) {\n return []\n }\n\n // Grab the enum from the schema\n if (data.schema.enum) {\n return data.schema.enum.map((item) => String(item))\n }\n\n // Grab the enum from the items schema\n if ('items' in data.schema) {\n const resolved = resolve.schema(data.schema.items)\n if (resolved?.enum) {\n return resolved.enum.map((item) => String(item))\n }\n }\n\n return []\n})\n\nconst minimumValue = computed(() =>\n data.schema && 'minimum' in data.schema ? data.schema.minimum : undefined,\n)\nconst maximumValue = computed(() =>\n data.schema && 'maximum' in data.schema ? data.schema.maximum : undefined,\n)\nconst typeValue = computed(() =>\n data.schema && 'type' in data.schema ? data.schema.type : undefined,\n)\n\nconst validationResult = computed(() =>\n validateParameter(data.schema, value.value),\n)\n\n/** Handle row updates while preserving existing properties */\nconst handleUpdateRow = (\n payload: Partial<{ name: string; value: string; isDisabled: boolean }>,\n): void => {\n // Update our local state\n if (payload.name !== undefined) {\n name.value = payload.name\n }\n if (payload.value !== undefined) {\n value.value = payload.value\n }\n\n // Is disabled should always be false unless you explicitly set it to true\n isDisabled.value = payload.isDisabled ?? false\n\n // Emit all of the local state\n emit('upsertRow', {\n name: name.value,\n value: value.value,\n isDisabled: isDisabled.value,\n })\n}\n</script>\n\n<template>\n <DataTableRow\n :id=\"data.name\"\n :class=\"{\n alert: validationResult.ok === false,\n error: validationResult.ok === false && invalidParams?.has(data.name),\n }\">\n <DataTableCheckbox\n class=\"!border-r\"\n :disabled=\"hasCheckboxDisabled ?? false\"\n :modelValue=\"!isDisabled\"\n @update:modelValue=\"(v) => handleUpdateRow({ isDisabled: !v })\" />\n\n <!-- Name -->\n <DataTableCell>\n <CodeInput\n :aria-label=\"`${label} Key`\"\n disableCloseBrackets\n :disabled=\"data.isReadonly\"\n disableEnter\n disableTabIndent\n :environment=\"environment\"\n lineWrapping\n :modelValue=\"name\"\n placeholder=\"Key\"\n :required=\"Boolean(data.isRequired)\"\n @navigate=\"(route) => emit('navigate', route)\"\n @selectVariable=\"(v: string) => handleUpdateRow({ name: v })\"\n @update:modelValue=\"(v) => handleUpdateRow({ name: v })\" />\n </DataTableCell>\n\n <!-- Value -->\n <DataTableCell>\n <CodeInput\n :aria-label=\"`${label} Value`\"\n class=\"pr-6 group-hover:pr-10 group-has-[.cm-focused]:pr-10\"\n :default=\"defaultValue\"\n disableCloseBrackets\n :disabled=\"data.isReadonly\"\n disableEnter\n disableTabIndent\n :enum=\"enumValue\"\n :environment=\"environment\"\n :examples=\"\n data.schema?.examples?.map((example) => String(example)) ?? []\n \"\n :linethrough=\"data.isOverridden\"\n lineWrapping\n :max=\"maximumValue\"\n :min=\"minimumValue\"\n :modelValue=\"displayValue\"\n placeholder=\"Value\"\n :type=\"typeValue\"\n withFakeData\n @navigate=\"(route) => emit('navigate', route)\"\n @update:modelValue=\"(v) => handleUpdateRow({ value: v })\">\n <template #icon>\n <ScalarButton\n v-if=\"\n Boolean(data.name || value) &&\n !data.isRequired &&\n data.isReadonly !== true\n \"\n class=\"text-c-2 hover:text-c-1 hover:bg-b-2 z-context -mr-0.5 hidden h-fit rounded p-1 group-hover:flex group-has-[.cm-focused]:flex\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"emit('deleteRow')\">\n <ScalarIconTrash class=\"size-3.5\" />\n </ScalarButton>\n\n <ScalarIconButton\n v-if=\"data.globalRoute !== undefined\"\n class=\"text-c-2 hover:text-c-1 hover:bg-b-2 z-context -mr-0.5 h-fit\"\n :icon=\"ScalarIconGlobe\"\n label=\"Global cookies are shared across the whole workspace. Click to navigate.\"\n size=\"xs\"\n tooltip=\"top\"\n variant=\"ghost\"\n @click=\"emit('navigate', data.globalRoute)\" />\n\n <RequestTableTooltip\n v-if=\"data.isReadonly\"\n description=\"This is a readonly property and you can not modify it! If you want to change it you have to override it or disable it using the checkbox\"\n :value=\"null\" />\n <RequestTableTooltip\n v-else-if=\"data.schema\"\n :description=\"data.description\"\n :schema=\"data.schema\"\n :value />\n </template>\n </CodeInput>\n </DataTableCell>\n\n <!-- File upload -->\n <DataTableCell\n v-if=\"showUploadButton\"\n class=\"group/upload flex items-center justify-center whitespace-nowrap\">\n <template v-if=\"isFile\">\n <div\n class=\"text-c-2 filemask flex w-full max-w-[100%] items-center justify-center overflow-hidden p-1\">\n <span>{{ displayValue }}</span>\n </div>\n <button\n class=\"bg-b-2 mt-1 block rounded p-0.5 text-center text-xs font-medium md:pointer-events-none md:absolute md:inset-x-1 md:top-1/2 md:mt-0 md:-translate-y-1/2 md:opacity-0 md:group-hover/upload:pointer-events-auto md:group-hover/upload:opacity-100\"\n type=\"button\"\n @click=\"emit('removeFile')\">\n Delete\n </button>\n </template>\n <template v-else>\n <div class=\"p-0.5\">\n <ScalarButton\n class=\"bg-b-2 hover:bg-b-3 text-c-2 h-fit border-0 py-px shadow-none\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"emit('uploadFile')\">\n <span>Select File</span>\n <ScalarIcon\n class=\"ml-1\"\n icon=\"Upload\"\n size=\"xs\"\n thickness=\"2.5\" />\n </ScalarButton>\n </div>\n </template>\n </DataTableCell>\n </DataTableRow>\n</template>\n"],"mappings":""}

@@ -140,2 +140,3 @@ import { getFileName } from "../helpers/files.js";

type: typeValue.value,
withFakeData: "",
onNavigate: _cache[6] || (_cache[6] = (route) => emit("navigate", route)),

@@ -142,0 +143,0 @@ "onUpdate:modelValue": _cache[7] || (_cache[7] = (v) => handleUpdateRow({ value: v }))

@@ -1,1 +0,1 @@

{"version":3,"file":"RequestTableRow.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/request-block/components/RequestTableRow.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton, ScalarIcon, ScalarIconButton } from '@scalar/components'\nimport { ScalarIconGlobe, ScalarIconTrash } from '@scalar/icons'\nimport type { ApiReferenceEvents } from '@scalar/workspace-store/events'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type {\n ParameterObject,\n SchemaObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, ref, watch } from 'vue'\n\nimport { getFileName } from '@/v2/blocks/request-block/helpers/files'\nimport { validateParameter } from '@/v2/blocks/request-block/helpers/validate-parameter'\nimport { CodeInput } from '@/v2/components/code-input'\nimport {\n DataTableCell,\n DataTableCheckbox,\n DataTableRow,\n} from '@/v2/components/data-table'\n\nimport RequestTableTooltip from './RequestTableTooltip.vue'\n\nexport type TableRow = {\n /** The parameter or field name/key */\n name: string\n /** The parameter value, can be a string, file, or null */\n value: string | File | null\n /** Optional description for the parameter */\n description?: string\n /** Optional route for global parameters (e.g., cookies shared across workspace) */\n globalRoute?: ApiReferenceEvents['ui:navigate']\n /** Whether the parameter is disabled/inactive */\n isDisabled?: boolean\n /** OpenAPI schema object with type, validation rules, examples, etc. */\n schema?: SchemaObject\n /** Whether the parameter is required */\n isRequired?: boolean\n /**\n * Whether the parameter is readonly and can not be modifies directly\n * User can still override the parameter which is going to show up with the linethrough style\n */\n isReadonly?: boolean\n /** Whether the parameter is overridden later on */\n isOverridden?: boolean\n /** Track the original parameter so we can update it */\n originalParameter?: ParameterObject\n}\n\nconst {\n data,\n environment,\n hasCheckboxDisabled,\n invalidParams,\n showUploadButton,\n} = defineProps<{\n data: TableRow\n hasCheckboxDisabled?: boolean\n invalidParams?: Set<string>\n label?: string\n environment: XScalarEnvironment\n showUploadButton?: boolean\n}>()\n\nconst emit = defineEmits<{\n (\n e: 'upsertRow',\n payload: { name: string; value: string | File; isDisabled: boolean },\n ): void\n (e: 'deleteRow'): void\n (e: 'uploadFile'): void\n (e: 'removeFile'): void\n (e: 'navigate', route: NonNullable<TableRow['globalRoute']>): void\n}>()\n\n/**\n * Track local state for the row\n *\n * Now this is required because of the way we get default values from the schema.\n * If we have a default value in data.value, then we update isDisabled to true. We lose the default value since now\n * we have an example where value: ''. This is why we need to track the local state and update all of the params at the\n * same time.\n */\nconst name = ref<string>(data.name ?? '')\nconst value = ref<string | File>(unpackProxyObject(data.value) ?? '')\nconst isDisabled = ref<boolean>(data.isDisabled ?? false)\n\n// Keep the above state synced with the data prop\nwatch(\n () => data.name,\n (newName) => (name.value = newName ?? ''),\n)\nwatch(\n () => data.value,\n (newValue) => (value.value = unpackProxyObject(newValue) ?? ''),\n)\nwatch(\n () => data.isDisabled,\n (newIsDisabled) => (isDisabled.value = newIsDisabled ?? false),\n)\n\n/** Check if the value is a File instance */\nconst isFile = computed(() => value.value instanceof File)\n\n/** Display value handles File instances and shows filename instead */\nconst displayValue = computed(\n () =>\n (isFile.value\n ? getFileName(value.value as File)\n : (value.value as string)) ?? '',\n)\n\nconst defaultValue = computed(() => data.schema?.default as string)\n\n/** See if we can extract enum values from the schema */\nconst enumValue = computed<string[]>(() => {\n if (!data.schema) {\n return []\n }\n\n // Grab the enum from the schema\n if (data.schema.enum) {\n return data.schema.enum.map((item) => String(item))\n }\n\n // Grab the enum from the items schema\n if ('items' in data.schema) {\n const resolved = resolve.schema(data.schema.items)\n if (resolved?.enum) {\n return resolved.enum.map((item) => String(item))\n }\n }\n\n return []\n})\n\nconst minimumValue = computed(() =>\n data.schema && 'minimum' in data.schema ? data.schema.minimum : undefined,\n)\nconst maximumValue = computed(() =>\n data.schema && 'maximum' in data.schema ? data.schema.maximum : undefined,\n)\nconst typeValue = computed(() =>\n data.schema && 'type' in data.schema ? data.schema.type : undefined,\n)\n\nconst validationResult = computed(() =>\n validateParameter(data.schema, value.value),\n)\n\n/** Handle row updates while preserving existing properties */\nconst handleUpdateRow = (\n payload: Partial<{ name: string; value: string; isDisabled: boolean }>,\n): void => {\n // Update our local state\n if (payload.name !== undefined) {\n name.value = payload.name\n }\n if (payload.value !== undefined) {\n value.value = payload.value\n }\n\n // Is disabled should always be false unless you explicitly set it to true\n isDisabled.value = payload.isDisabled ?? false\n\n // Emit all of the local state\n emit('upsertRow', {\n name: name.value,\n value: value.value,\n isDisabled: isDisabled.value,\n })\n}\n</script>\n\n<template>\n <DataTableRow\n :id=\"data.name\"\n :class=\"{\n alert: validationResult.ok === false,\n error: validationResult.ok === false && invalidParams?.has(data.name),\n }\">\n <DataTableCheckbox\n class=\"!border-r\"\n :disabled=\"hasCheckboxDisabled ?? false\"\n :modelValue=\"!isDisabled\"\n @update:modelValue=\"(v) => handleUpdateRow({ isDisabled: !v })\" />\n\n <!-- Name -->\n <DataTableCell>\n <CodeInput\n :aria-label=\"`${label} Key`\"\n disableCloseBrackets\n :disabled=\"data.isReadonly\"\n disableEnter\n disableTabIndent\n :environment=\"environment\"\n lineWrapping\n :modelValue=\"name\"\n placeholder=\"Key\"\n :required=\"Boolean(data.isRequired)\"\n @navigate=\"(route) => emit('navigate', route)\"\n @selectVariable=\"(v: string) => handleUpdateRow({ name: v })\"\n @update:modelValue=\"(v) => handleUpdateRow({ name: v })\" />\n </DataTableCell>\n\n <!-- Value -->\n <DataTableCell>\n <CodeInput\n :aria-label=\"`${label} Value`\"\n class=\"pr-6 group-hover:pr-10 group-has-[.cm-focused]:pr-10\"\n :default=\"defaultValue\"\n disableCloseBrackets\n :disabled=\"data.isReadonly\"\n disableEnter\n disableTabIndent\n :enum=\"enumValue\"\n :environment=\"environment\"\n :examples=\"\n data.schema?.examples?.map((example) => String(example)) ?? []\n \"\n :linethrough=\"data.isOverridden\"\n lineWrapping\n :max=\"maximumValue\"\n :min=\"minimumValue\"\n :modelValue=\"displayValue\"\n placeholder=\"Value\"\n :type=\"typeValue\"\n @navigate=\"(route) => emit('navigate', route)\"\n @update:modelValue=\"(v) => handleUpdateRow({ value: v })\">\n <template #icon>\n <ScalarButton\n v-if=\"\n Boolean(data.name || value) &&\n !data.isRequired &&\n data.isReadonly !== true\n \"\n class=\"text-c-2 hover:text-c-1 hover:bg-b-2 z-context -mr-0.5 hidden h-fit rounded p-1 group-hover:flex group-has-[.cm-focused]:flex\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"emit('deleteRow')\">\n <ScalarIconTrash class=\"size-3.5\" />\n </ScalarButton>\n\n <ScalarIconButton\n v-if=\"data.globalRoute !== undefined\"\n class=\"text-c-2 hover:text-c-1 hover:bg-b-2 z-context -mr-0.5 h-fit\"\n :icon=\"ScalarIconGlobe\"\n label=\"Global cookies are shared across the whole workspace. Click to navigate.\"\n size=\"xs\"\n tooltip=\"top\"\n variant=\"ghost\"\n @click=\"emit('navigate', data.globalRoute)\" />\n\n <RequestTableTooltip\n v-if=\"data.isReadonly\"\n description=\"This is a readonly property and you can not modify it! If you want to change it you have to override it or disable it using the checkbox\"\n :value=\"null\" />\n <RequestTableTooltip\n v-else-if=\"data.schema\"\n :description=\"data.description\"\n :schema=\"data.schema\"\n :value />\n </template>\n </CodeInput>\n </DataTableCell>\n\n <!-- File upload -->\n <DataTableCell\n v-if=\"showUploadButton\"\n class=\"group/upload flex items-center justify-center whitespace-nowrap\">\n <template v-if=\"isFile\">\n <div\n class=\"text-c-2 filemask flex w-full max-w-[100%] items-center justify-center overflow-hidden p-1\">\n <span>{{ displayValue }}</span>\n </div>\n <button\n class=\"bg-b-2 mt-1 block rounded p-0.5 text-center text-xs font-medium md:pointer-events-none md:absolute md:inset-x-1 md:top-1/2 md:mt-0 md:-translate-y-1/2 md:opacity-0 md:group-hover/upload:pointer-events-auto md:group-hover/upload:opacity-100\"\n type=\"button\"\n @click=\"emit('removeFile')\">\n Delete\n </button>\n </template>\n <template v-else>\n <div class=\"p-0.5\">\n <ScalarButton\n class=\"bg-b-2 hover:bg-b-3 text-c-2 h-fit border-0 py-px shadow-none\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"emit('uploadFile')\">\n <span>Select File</span>\n <ScalarIcon\n class=\"ml-1\"\n icon=\"Upload\"\n size=\"xs\"\n thickness=\"2.5\" />\n </ScalarButton>\n </div>\n </template>\n </DataTableCell>\n </DataTableRow>\n</template>\n"],"mappings":"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"}
{"version":3,"file":"RequestTableRow.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/request-block/components/RequestTableRow.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton, ScalarIcon, ScalarIconButton } from '@scalar/components'\nimport { ScalarIconGlobe, ScalarIconTrash } from '@scalar/icons'\nimport type { ApiReferenceEvents } from '@scalar/workspace-store/events'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport { resolve } from '@scalar/workspace-store/resolve'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type {\n ParameterObject,\n SchemaObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, ref, watch } from 'vue'\n\nimport { getFileName } from '@/v2/blocks/request-block/helpers/files'\nimport { validateParameter } from '@/v2/blocks/request-block/helpers/validate-parameter'\nimport { CodeInput } from '@/v2/components/code-input'\nimport {\n DataTableCell,\n DataTableCheckbox,\n DataTableRow,\n} from '@/v2/components/data-table'\n\nimport RequestTableTooltip from './RequestTableTooltip.vue'\n\nexport type TableRow = {\n /** The parameter or field name/key */\n name: string\n /** The parameter value, can be a string, file, or null */\n value: string | File | null\n /** Optional description for the parameter */\n description?: string\n /** Optional route for global parameters (e.g., cookies shared across workspace) */\n globalRoute?: ApiReferenceEvents['ui:navigate']\n /** Whether the parameter is disabled/inactive */\n isDisabled?: boolean\n /** OpenAPI schema object with type, validation rules, examples, etc. */\n schema?: SchemaObject\n /** Whether the parameter is required */\n isRequired?: boolean\n /**\n * Whether the parameter is readonly and can not be modifies directly\n * User can still override the parameter which is going to show up with the linethrough style\n */\n isReadonly?: boolean\n /** Whether the parameter is overridden later on */\n isOverridden?: boolean\n /** Track the original parameter so we can update it */\n originalParameter?: ParameterObject\n}\n\nconst {\n data,\n environment,\n hasCheckboxDisabled,\n invalidParams,\n showUploadButton,\n} = defineProps<{\n data: TableRow\n hasCheckboxDisabled?: boolean\n invalidParams?: Set<string>\n label?: string\n environment: XScalarEnvironment\n showUploadButton?: boolean\n}>()\n\nconst emit = defineEmits<{\n (\n e: 'upsertRow',\n payload: { name: string; value: string | File; isDisabled: boolean },\n ): void\n (e: 'deleteRow'): void\n (e: 'uploadFile'): void\n (e: 'removeFile'): void\n (e: 'navigate', route: NonNullable<TableRow['globalRoute']>): void\n}>()\n\n/**\n * Track local state for the row\n *\n * Now this is required because of the way we get default values from the schema.\n * If we have a default value in data.value, then we update isDisabled to true. We lose the default value since now\n * we have an example where value: ''. This is why we need to track the local state and update all of the params at the\n * same time.\n */\nconst name = ref<string>(data.name ?? '')\nconst value = ref<string | File>(unpackProxyObject(data.value) ?? '')\nconst isDisabled = ref<boolean>(data.isDisabled ?? false)\n\n// Keep the above state synced with the data prop\nwatch(\n () => data.name,\n (newName) => (name.value = newName ?? ''),\n)\nwatch(\n () => data.value,\n (newValue) => (value.value = unpackProxyObject(newValue) ?? ''),\n)\nwatch(\n () => data.isDisabled,\n (newIsDisabled) => (isDisabled.value = newIsDisabled ?? false),\n)\n\n/** Check if the value is a File instance */\nconst isFile = computed(() => value.value instanceof File)\n\n/** Display value handles File instances and shows filename instead */\nconst displayValue = computed(\n () =>\n (isFile.value\n ? getFileName(value.value as File)\n : (value.value as string)) ?? '',\n)\n\nconst defaultValue = computed(() => data.schema?.default as string)\n\n/** See if we can extract enum values from the schema */\nconst enumValue = computed<string[]>(() => {\n if (!data.schema) {\n return []\n }\n\n // Grab the enum from the schema\n if (data.schema.enum) {\n return data.schema.enum.map((item) => String(item))\n }\n\n // Grab the enum from the items schema\n if ('items' in data.schema) {\n const resolved = resolve.schema(data.schema.items)\n if (resolved?.enum) {\n return resolved.enum.map((item) => String(item))\n }\n }\n\n return []\n})\n\nconst minimumValue = computed(() =>\n data.schema && 'minimum' in data.schema ? data.schema.minimum : undefined,\n)\nconst maximumValue = computed(() =>\n data.schema && 'maximum' in data.schema ? data.schema.maximum : undefined,\n)\nconst typeValue = computed(() =>\n data.schema && 'type' in data.schema ? data.schema.type : undefined,\n)\n\nconst validationResult = computed(() =>\n validateParameter(data.schema, value.value),\n)\n\n/** Handle row updates while preserving existing properties */\nconst handleUpdateRow = (\n payload: Partial<{ name: string; value: string; isDisabled: boolean }>,\n): void => {\n // Update our local state\n if (payload.name !== undefined) {\n name.value = payload.name\n }\n if (payload.value !== undefined) {\n value.value = payload.value\n }\n\n // Is disabled should always be false unless you explicitly set it to true\n isDisabled.value = payload.isDisabled ?? false\n\n // Emit all of the local state\n emit('upsertRow', {\n name: name.value,\n value: value.value,\n isDisabled: isDisabled.value,\n })\n}\n</script>\n\n<template>\n <DataTableRow\n :id=\"data.name\"\n :class=\"{\n alert: validationResult.ok === false,\n error: validationResult.ok === false && invalidParams?.has(data.name),\n }\">\n <DataTableCheckbox\n class=\"!border-r\"\n :disabled=\"hasCheckboxDisabled ?? false\"\n :modelValue=\"!isDisabled\"\n @update:modelValue=\"(v) => handleUpdateRow({ isDisabled: !v })\" />\n\n <!-- Name -->\n <DataTableCell>\n <CodeInput\n :aria-label=\"`${label} Key`\"\n disableCloseBrackets\n :disabled=\"data.isReadonly\"\n disableEnter\n disableTabIndent\n :environment=\"environment\"\n lineWrapping\n :modelValue=\"name\"\n placeholder=\"Key\"\n :required=\"Boolean(data.isRequired)\"\n @navigate=\"(route) => emit('navigate', route)\"\n @selectVariable=\"(v: string) => handleUpdateRow({ name: v })\"\n @update:modelValue=\"(v) => handleUpdateRow({ name: v })\" />\n </DataTableCell>\n\n <!-- Value -->\n <DataTableCell>\n <CodeInput\n :aria-label=\"`${label} Value`\"\n class=\"pr-6 group-hover:pr-10 group-has-[.cm-focused]:pr-10\"\n :default=\"defaultValue\"\n disableCloseBrackets\n :disabled=\"data.isReadonly\"\n disableEnter\n disableTabIndent\n :enum=\"enumValue\"\n :environment=\"environment\"\n :examples=\"\n data.schema?.examples?.map((example) => String(example)) ?? []\n \"\n :linethrough=\"data.isOverridden\"\n lineWrapping\n :max=\"maximumValue\"\n :min=\"minimumValue\"\n :modelValue=\"displayValue\"\n placeholder=\"Value\"\n :type=\"typeValue\"\n withFakeData\n @navigate=\"(route) => emit('navigate', route)\"\n @update:modelValue=\"(v) => handleUpdateRow({ value: v })\">\n <template #icon>\n <ScalarButton\n v-if=\"\n Boolean(data.name || value) &&\n !data.isRequired &&\n data.isReadonly !== true\n \"\n class=\"text-c-2 hover:text-c-1 hover:bg-b-2 z-context -mr-0.5 hidden h-fit rounded p-1 group-hover:flex group-has-[.cm-focused]:flex\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"emit('deleteRow')\">\n <ScalarIconTrash class=\"size-3.5\" />\n </ScalarButton>\n\n <ScalarIconButton\n v-if=\"data.globalRoute !== undefined\"\n class=\"text-c-2 hover:text-c-1 hover:bg-b-2 z-context -mr-0.5 h-fit\"\n :icon=\"ScalarIconGlobe\"\n label=\"Global cookies are shared across the whole workspace. Click to navigate.\"\n size=\"xs\"\n tooltip=\"top\"\n variant=\"ghost\"\n @click=\"emit('navigate', data.globalRoute)\" />\n\n <RequestTableTooltip\n v-if=\"data.isReadonly\"\n description=\"This is a readonly property and you can not modify it! If you want to change it you have to override it or disable it using the checkbox\"\n :value=\"null\" />\n <RequestTableTooltip\n v-else-if=\"data.schema\"\n :description=\"data.description\"\n :schema=\"data.schema\"\n :value />\n </template>\n </CodeInput>\n </DataTableCell>\n\n <!-- File upload -->\n <DataTableCell\n v-if=\"showUploadButton\"\n class=\"group/upload flex items-center justify-center whitespace-nowrap\">\n <template v-if=\"isFile\">\n <div\n class=\"text-c-2 filemask flex w-full max-w-[100%] items-center justify-center overflow-hidden p-1\">\n <span>{{ displayValue }}</span>\n </div>\n <button\n class=\"bg-b-2 mt-1 block rounded p-0.5 text-center text-xs font-medium md:pointer-events-none md:absolute md:inset-x-1 md:top-1/2 md:mt-0 md:-translate-y-1/2 md:opacity-0 md:group-hover/upload:pointer-events-auto md:group-hover/upload:opacity-100\"\n type=\"button\"\n @click=\"emit('removeFile')\">\n Delete\n </button>\n </template>\n <template v-else>\n <div class=\"p-0.5\">\n <ScalarButton\n class=\"bg-b-2 hover:bg-b-3 text-c-2 h-fit border-0 py-px shadow-none\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"emit('uploadFile')\">\n <span>Select File</span>\n <ScalarIcon\n class=\"ml-1\"\n icon=\"Upload\"\n size=\"xs\"\n thickness=\"2.5\" />\n </ScalarButton>\n </div>\n </template>\n </DataTableCell>\n </DataTableRow>\n</template>\n"],"mappings":"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"}

@@ -1,1 +0,1 @@

{"version":3,"file":"RequestBlock.vue.script.js","names":[],"sources":["../../../../src/v2/blocks/request-block/RequestBlock.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarErrorBoundary } from '@scalar/components'\nimport { canMethodHaveBody } from '@scalar/helpers/http/can-method-have-body'\nimport type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport { REGEX } from '@scalar/helpers/regex/regex-helpers'\nimport { replaceEnvVariables } from '@scalar/helpers/regex/replace-variables'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { SelectedSecurity } from '@scalar/workspace-store/entities/auth'\nimport type {\n ApiReferenceEvents,\n AuthMeta,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport {\n filterGlobalCookie,\n getEnvironmentVariables,\n getExample,\n getResolvedUrl,\n type MergedSecuritySchemes,\n type SecuritySchemeObjectSecret,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type {\n OpenApiDocument,\n OperationObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, ref, useId, watch } from 'vue'\n\nimport SectionFilter from '@/components/SectionFilter.vue'\nimport ViewLayoutSection from '@/components/ViewLayout/ViewLayoutSection.vue'\nimport type { ClientOptionGroup } from '@/v2/blocks/operation-code-sample'\nimport RequestBody from '@/v2/blocks/request-block/components/RequestBody.vue'\nimport RequestCodeSnippet from '@/v2/blocks/request-block/components/RequestCodeSnippet.vue'\nimport RequestParams from '@/v2/blocks/request-block/components/RequestParams.vue'\nimport type { TableRow } from '@/v2/blocks/request-block/components/RequestTableRow.vue'\nimport { createParameterHandlers } from '@/v2/blocks/request-block/helpers/create-parameter-handlers'\nimport { getParameterSchema } from '@/v2/blocks/request-block/helpers/get-parameter-schema'\nimport { groupBy } from '@/v2/blocks/request-block/helpers/group-by'\nimport { isParamDisabled } from '@/v2/blocks/request-block/helpers/is-param-disabled'\nimport { AuthSelector } from '@/v2/blocks/scalar-auth-selector-block'\nimport type { OAuth2Options } from '@/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue'\nimport type { ClientLayout } from '@/v2/types/layout'\n\ntype Filter =\n | 'All'\n | 'Auth'\n | 'Variables'\n | 'Cookies'\n | 'Headers'\n | 'Query'\n | 'Body'\n\nexport type RequestBlockProps = {\n authMeta: AuthMeta\n clientOptions: ClientOptionGroup[]\n environment: XScalarEnvironment\n eventBus: WorkspaceEventBus\n exampleKey: string\n workspaceCookies: XScalarCookie[]\n documentCookies: XScalarCookie[]\n layout: ClientLayout\n method: HttpMethod\n operation: OperationObject\n path: string\n plugins: ClientPlugin[]\n proxyUrl: string\n securityRequirements: OpenApiDocument['security']\n securitySchemes: MergedSecuritySchemes\n requestBodyCompositionSelection?: Record<string, number>\n selectedClient: WorkspaceStore['workspace']['x-scalar-default-client']\n selectedSecurity: SelectedSecurity\n selectedSecuritySchemes: SecuritySchemeObjectSecret[]\n server: ServerObject | null\n defaultHeaders: Record<string, string>\n /** Any config options required for the OAuth2 flow */\n options?: OAuth2Options\n}\n\nconst {\n authMeta = { type: 'document' },\n clientOptions,\n environment,\n eventBus,\n exampleKey,\n workspaceCookies,\n documentCookies,\n layout,\n method,\n operation,\n path,\n plugins,\n proxyUrl,\n requestBodyCompositionSelection,\n securityRequirements,\n securitySchemes,\n selectedClient,\n selectedSecurity,\n selectedSecuritySchemes,\n server,\n defaultHeaders: autoGeneratedHeaders,\n} = defineProps<RequestBlockProps>()\n\n/** Operation metadata used across event emissions */\nconst meta = computed(() => ({\n method,\n path,\n exampleKey,\n}))\n\n/** Parameters grouped by type (path, query, header, cookie) */\nconst sections = computed(() =>\n groupBy(\n operation.parameters?.map((param) => getResolvedRef(param)) ?? [],\n 'in',\n (param) => {\n const example = getExample(param, exampleKey, undefined)\n\n return {\n name: param.name,\n value: example?.value ?? '',\n description: param.description,\n schema: getParameterSchema(param),\n isRequired: param.required,\n isDisabled: isParamDisabled(param, example),\n originalParameter: param,\n } as TableRow\n },\n ),\n)\n\n// Generate a reverse map for fast lookup of headers by the name\nconst headersMap = computed(() =>\n groupBy(\n sections.value.header?.map((it) => ({\n ...it,\n name: it.name.toLowerCase(),\n })) ?? [],\n 'name',\n ),\n)\n\nconst defaultHeaders = computed(() => {\n const disableParameters =\n operation['x-scalar-disable-parameters']?.['default-headers']?.[\n exampleKey\n ] ?? {}\n\n const isOverridden = (name: string) => {\n const header = headersMap.value[name.toLowerCase()]?.[0]\n\n if (!header) {\n return false\n }\n\n return !header.isDisabled\n }\n\n return Object.entries(autoGeneratedHeaders).map(([name, value]) => {\n return {\n name,\n value,\n schema: undefined,\n isOverridden: isOverridden(name),\n isReadonly: true,\n isDisabled: disableParameters[name.toLowerCase()] ?? false,\n } satisfies TableRow\n })\n})\n\nconst headers = computed(() => [\n ...defaultHeaders.value,\n ...(sections.value.header ?? []),\n])\n\nconst defaultCookies = computed(() => {\n const environmentVariables = getEnvironmentVariables(environment)\n const resolvedUrl = getResolvedUrl({\n server,\n path,\n })\n const url = replaceEnvVariables(resolvedUrl, environmentVariables)\n\n const disabledGlobalCookies =\n operation['x-scalar-disable-parameters']?.['global-cookies']?.[\n exampleKey\n ] ?? {}\n\n const transform = (\n cookie: XScalarCookie,\n location: 'document' | 'workspace',\n ) => {\n return {\n name: cookie.name,\n value: cookie.value,\n globalRoute: { page: location, path: 'cookies' } as const,\n isReadonly: true,\n isDisabled: disabledGlobalCookies[cookie.name.toLowerCase()] ?? false,\n } satisfies TableRow\n }\n\n const globalCookies = [\n {\n location: 'workspace',\n cookies: workspaceCookies,\n },\n {\n location: 'document',\n cookies: documentCookies,\n },\n ] as const\n\n return globalCookies.flatMap(({ location, cookies }) => {\n return cookies\n .filter((cookie) =>\n filterGlobalCookie({\n cookie,\n url,\n disabledGlobalCookies: {},\n }),\n )\n .map((cookie) => transform(cookie, location))\n })\n})\n\nconst cookies = computed(() => [\n ...(defaultCookies.value ?? []),\n ...(sections.value.cookie ?? []),\n])\n\n/** Currently selected filter for the request sections */\nconst selectedFilter = ref<Filter>('All')\n\n/** Available operation sections */\nconst OPERATION_SECTIONS: readonly Filter[] = [\n 'Auth',\n 'Variables',\n 'Cookies',\n 'Headers',\n 'Query',\n 'Body',\n] as const\n\n/**\n * Pre-generated stable IDs for all possible filter sections.\n * These are created once at setup time to avoid regenerating IDs on re-render.\n */\nconst sectionIds: Record<Filter, string> = {\n All: useId(),\n Auth: useId(),\n Variables: useId(),\n Cookies: useId(),\n Headers: useId(),\n Query: useId(),\n Body: useId(),\n}\n\n/** Filters available based on operation state */\nconst filters = computed<Filter[]>(() => {\n const availableFilters = new Set<Filter>(['All', ...OPERATION_SECTIONS])\n\n if (!sections.value.path?.length) {\n availableFilters.delete('Variables')\n }\n if (!canMethodHaveBody(method)) {\n availableFilters.delete('Body')\n }\n if (isAuthHidden.value) {\n availableFilters.delete('Auth')\n }\n\n return [...availableFilters]\n})\n\n/**\n * Map available filters to their pre-generated stable IDs.\n * Only includes IDs for filters that are currently available.\n */\nconst filterIds = computed(\n () =>\n Object.fromEntries(\n filters.value.map((section) => [section, sectionIds[section]]),\n ) as Record<Filter, string>,\n)\n\n/**\n * Hide auth selector in readonly mode when no security schemes are defined.\n * This keeps the UI clean when there are no authentication options available.\n */\nconst isAuthHidden = computed(\n () => layout === 'modal' && !Object.keys(securitySchemes ?? {}).length,\n)\n\n/**\n * Keep auth available for unauthenticated operations, but collapse it by default\n * in readonly modal layouts unless a requirement or manual selection exists.\n */\nconst isAuthDefaultOpen = computed(\n () =>\n layout !== 'modal' ||\n Boolean(\n securityRequirements?.length || selectedSecurity.selectedSchemes.length,\n ),\n)\n\n/** Get a sensible placeholder for the request name input */\nconst requestNamePlaceholder = computed(() => {\n if (operation.summary) {\n return operation.summary\n }\n const cleanPath = path.replace(REGEX.PROTOCOL, '')\n return cleanPath || 'Request Name'\n})\n\n/** Check if the section should be shown based on the selected filter */\nconst isSectionVisible = (section: Filter): boolean => {\n return selectedFilter.value === 'All' || selectedFilter.value === section\n}\n\n/**\n * Reset filter to 'All' if Body filter is selected but method changes to one that cannot have a body.\n * This prevents showing an empty Body section when switching methods.\n */\nwatch(\n () => method,\n (newMethod) => {\n if (selectedFilter.value === 'Body' && !canMethodHaveBody(newMethod)) {\n selectedFilter.value = 'All'\n }\n },\n)\n\n/** Handle operation summary updates */\nconst handleSummaryUpdate = (event: Event): void => {\n const summary = (event.target as HTMLInputElement).value\n eventBus.emit('operation:update:meta', {\n meta: meta.value,\n payload: { summary: summary.trim() },\n })\n}\n\n/** Parameter handlers */\nconst parameterHandlers = computed(() => ({\n path: createParameterHandlers('path', eventBus, meta.value, {\n context: sections.value.path ?? [],\n }),\n cookie: createParameterHandlers('cookie', eventBus, meta.value, {\n context: cookies.value ?? [],\n globalParameters: defaultCookies.value.length,\n }),\n header: createParameterHandlers('header', eventBus, meta.value, {\n context: headers.value,\n defaultParameters: defaultHeaders.value.length,\n }),\n query: createParameterHandlers('query', eventBus, meta.value, {\n context: sections.value.query ?? [],\n }),\n}))\n\n/** Handle request body content type update */\nconst handleUpdateContentType = (payload: { value: string }): void =>\n eventBus.emit('operation:update:requestBody:contentType', {\n payload: { contentType: payload.value },\n meta: meta.value,\n })\n\n/** Handle request body value update */\nconst handleUpdateBodyValue = ({\n payload,\n contentType,\n}: Pick<\n ApiReferenceEvents['operation:update:requestBody:value'],\n 'payload' | 'contentType'\n>): void => {\n const debounceKey =\n typeof payload === 'string'\n ? `update:requestBody:value-${contentType}`\n : undefined\n\n eventBus.emit(\n 'operation:update:requestBody:value',\n {\n payload,\n contentType,\n meta: meta.value,\n },\n {\n debounceKey,\n },\n )\n}\n\n/** Handle request body value update */\nconst handleUpdateBodyFormValue = ({\n payload,\n contentType,\n}: Pick<\n ApiReferenceEvents['operation:update:requestBody:formValue'],\n 'payload' | 'contentType'\n>): void => {\n const debounceKey = `update:requestBody:${contentType}-form-value`\n\n eventBus.emit(\n 'operation:update:requestBody:formValue',\n {\n payload: payload.map((row) => unpackProxyObject(row, { depth: 1 })),\n contentType,\n meta: meta.value,\n },\n {\n debounceKey,\n },\n )\n}\n\nconst labelRequestNameId = useId()\n\nconst globalCookies = computed(() => [...workspaceCookies, ...documentCookies])\n\n/** Allow updating the operation extensions for the plugins */\nconst updateOperationExtension = (\n payload: ApiReferenceEvents['operation:update:extension']['payload'],\n): void =>\n eventBus.emit('operation:update:extension', { payload, meta: meta.value })\n</script>\n<template>\n <ViewLayoutSection :aria-label=\"`Request: ${operation.summary}`\">\n <template #title>\n <div\n class=\"group pointer-events-none flex flex-1 items-center gap-1 lg:pr-24\">\n <label\n v-if=\"layout !== 'modal'\"\n class=\"pointer-events-auto absolute top-0 left-0 h-full w-full cursor-text opacity-0\"\n :for=\"labelRequestNameId\" />\n <input\n v-if=\"layout !== 'modal'\"\n :id=\"labelRequestNameId\"\n class=\"text-c-1 group-hover-input pointer-events-auto relative z-10 -ml-0.5 h-8 w-full rounded pl-1.25 has-[:focus-visible]:outline md:-ml-1.25\"\n :placeholder=\"requestNamePlaceholder\"\n :value=\"operation.summary\"\n @blur=\"handleSummaryUpdate\" />\n <span\n v-else\n class=\"text-c-1 flex h-8 items-center\">\n {{ operation.summary }}\n </span>\n </div>\n <SectionFilter\n v-model=\"selectedFilter\"\n :filterIds=\"filterIds\"\n :filters=\"filters\" />\n </template>\n\n <div\n :id=\"filterIds.All\"\n class=\"request-section-content custom-scroll relative flex flex-1 flex-col\"\n :role=\"selectedFilter === 'All' ? 'tabpanel' : 'none'\">\n <!-- Auth Selector -->\n <AuthSelector\n v-show=\"isSectionVisible('Auth') && !isAuthHidden\"\n :id=\"filterIds.Auth\"\n :createAnySecurityScheme=\"layout !== 'modal'\"\n :defaultOpen=\"isAuthDefaultOpen\"\n :environment\n :eventBus\n :meta=\"authMeta\"\n :options\n :proxyUrl\n :securityRequirements\n :securitySchemes\n :selectedSecurity\n :selectedSecuritySchemes\n :server\n title=\"Authentication\" />\n\n <!-- Variables (Path Parameters) -->\n <RequestParams\n v-show=\"isSectionVisible('Variables') && sections.path?.length\"\n :id=\"filterIds.Variables\"\n :environment\n :eventBus\n :exampleKey\n :rows=\"sections.path ?? []\"\n :showAddRowPlaceholder=\"false\"\n title=\"Variables\"\n v-on=\"parameterHandlers.path\" />\n\n <!-- Cookies -->\n <RequestParams\n v-show=\"isSectionVisible('Cookies')\"\n :id=\"filterIds.Cookies\"\n :environment\n :eventBus\n :exampleKey\n :rows=\"cookies ?? []\"\n :showAddRowPlaceholder=\"true\"\n title=\"Cookies\"\n v-on=\"parameterHandlers.cookie\" />\n\n <!-- Headers -->\n <RequestParams\n v-show=\"isSectionVisible('Headers')\"\n :id=\"filterIds.Headers\"\n :environment\n :eventBus\n :exampleKey\n :rows=\"headers ?? []\"\n title=\"Headers\"\n v-on=\"parameterHandlers.header\" />\n\n <!-- Query Parameters -->\n <RequestParams\n v-show=\"isSectionVisible('Query')\"\n :id=\"filterIds.Query\"\n :environment\n :eventBus\n :exampleKey\n :rows=\"sections.query ?? []\"\n title=\"Query Parameters\"\n v-on=\"parameterHandlers.query\" />\n\n <!-- Request Body -->\n <RequestBody\n v-show=\"isSectionVisible('Body') && canMethodHaveBody(method)\"\n :id=\"filterIds.Body\"\n :environment\n :exampleKey\n :requestBody=\"getResolvedRef(operation.requestBody)\"\n :requestBodyCompositionSelection\n title=\"Request Body\"\n @update:contentType=\"handleUpdateContentType\"\n @update:formValue=\"handleUpdateBodyFormValue\"\n @update:value=\"handleUpdateBodyValue\" />\n\n <!-- Inject request section plugin components -->\n <ScalarErrorBoundary\n v-for=\"(plugin, index) in plugins\"\n :key=\"index\">\n <component\n :is=\"plugin.components.request.component\"\n v-if=\"plugin?.components?.request\"\n v-show=\"selectedFilter === 'All'\"\n :operation\n v-bind=\"plugin.components.request.additionalProps\"\n @operation:update:extension=\"updateOperationExtension\" />\n </ScalarErrorBoundary>\n\n <!-- Spacer -->\n <div class=\"flex grow\" />\n <!-- Code Snippet -->\n <RequestCodeSnippet\n v-show=\"selectedFilter === 'All'\"\n :clientOptions\n :eventBus\n :globalCookies\n integration=\"client\"\n :method\n :operation\n :path\n :securitySchemes=\"selectedSecuritySchemes\"\n :selectedClient\n :selectedContentType=\"\n getResolvedRef(operation.requestBody)?.[\n 'x-scalar-selected-content-type'\n ]?.[exampleKey]\n \"\n :selectedServer=\"server ?? undefined\" />\n </div>\n </ViewLayoutSection>\n</template>\n<style scoped>\n.request-section-content {\n --scalar-border-width: 0.5px;\n}\n.request-section-content-filter {\n box-shadow: 0 -10px 0 10px var(--scalar-background-1);\n}\n.request-item:focus-within .request-meta-buttons {\n opacity: 1;\n}\n.group-hover-input {\n border-width: var(--scalar-border-width);\n border-color: transparent;\n}\n.group:hover .group-hover-input {\n background: color-mix(\n in srgb,\n var(--scalar-background-1),\n var(--scalar-background-2)\n );\n border-color: var(--scalar-border-color);\n}\n.group-hover-input:focus {\n background: transparent !important;\n border-color: var(--scalar-border-color) !important;\n}\n</style>\n"],"mappings":"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"}
{"version":3,"file":"RequestBlock.vue.script.js","names":[],"sources":["../../../../src/v2/blocks/request-block/RequestBlock.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarErrorBoundary } from '@scalar/components'\nimport { canMethodHaveBody } from '@scalar/helpers/http/can-method-have-body'\nimport type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport { REGEX } from '@scalar/helpers/regex/regex-helpers'\nimport { replaceEnvVariables } from '@scalar/helpers/regex/replace-variables'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { SelectedSecurity } from '@scalar/workspace-store/entities/auth'\nimport type {\n ApiReferenceEvents,\n AuthMeta,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport {\n filterGlobalCookie,\n getEnvironmentVariables,\n getExample,\n getResolvedUrl,\n type MergedSecuritySchemes,\n type SecuritySchemeObjectSecret,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport type {\n OpenApiDocument,\n OperationObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, ref, useId, watch } from 'vue'\n\nimport SectionFilter from '@/components/SectionFilter.vue'\nimport ViewLayoutSection from '@/components/ViewLayout/ViewLayoutSection.vue'\nimport type { ClientOptionGroup } from '@/v2/blocks/operation-code-sample'\nimport RequestBody from '@/v2/blocks/request-block/components/RequestBody.vue'\nimport RequestCodeSnippet from '@/v2/blocks/request-block/components/RequestCodeSnippet.vue'\nimport RequestParams from '@/v2/blocks/request-block/components/RequestParams.vue'\nimport type { TableRow } from '@/v2/blocks/request-block/components/RequestTableRow.vue'\nimport { createParameterHandlers } from '@/v2/blocks/request-block/helpers/create-parameter-handlers'\nimport { getParameterSchema } from '@/v2/blocks/request-block/helpers/get-parameter-schema'\nimport { groupBy } from '@/v2/blocks/request-block/helpers/group-by'\nimport { isParamDisabled } from '@/v2/blocks/request-block/helpers/is-param-disabled'\nimport { AuthSelector } from '@/v2/blocks/scalar-auth-selector-block'\nimport type { OAuth2Options } from '@/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue'\nimport type { ClientLayout } from '@/v2/types/layout'\n\ntype Filter =\n | 'All'\n | 'Auth'\n | 'Variables'\n | 'Cookies'\n | 'Headers'\n | 'Query'\n | 'Body'\n\nexport type RequestBlockProps = {\n authMeta: AuthMeta\n clientOptions: ClientOptionGroup[]\n environment: XScalarEnvironment\n eventBus: WorkspaceEventBus\n exampleKey: string\n workspaceCookies: XScalarCookie[]\n documentCookies: XScalarCookie[]\n layout: ClientLayout\n method: HttpMethod\n operation: OperationObject\n path: string\n plugins: ClientPlugin[]\n proxyUrl: string\n securityRequirements: OpenApiDocument['security']\n securitySchemes: MergedSecuritySchemes\n requestBodyCompositionSelection?: Record<string, number>\n selectedClient: WorkspaceStore['workspace']['x-scalar-default-client']\n selectedSecurity: SelectedSecurity\n selectedSecuritySchemes: SecuritySchemeObjectSecret[]\n server: ServerObject | null\n defaultHeaders: Record<string, string>\n /** Any config options required for the OAuth2 flow */\n options?: OAuth2Options\n}\n\nconst {\n authMeta = { type: 'document' },\n clientOptions,\n environment,\n eventBus,\n exampleKey,\n workspaceCookies,\n documentCookies,\n layout,\n method,\n operation,\n path,\n plugins,\n proxyUrl,\n requestBodyCompositionSelection,\n securityRequirements,\n securitySchemes,\n selectedClient,\n selectedSecurity,\n selectedSecuritySchemes,\n server,\n defaultHeaders: autoGeneratedHeaders,\n} = defineProps<RequestBlockProps>()\n\n/** Operation metadata used across event emissions */\nconst meta = computed(() => ({\n method,\n path,\n exampleKey,\n}))\n\n/** Parameters grouped by type (path, query, header, cookie) */\nconst sections = computed(() =>\n groupBy(\n operation.parameters?.map((param) => getResolvedRef(param)) ?? [],\n 'in',\n (param) => {\n const example = getExample(param, exampleKey, undefined)\n\n return {\n name: param.name,\n value: example?.value ?? '',\n description: param.description,\n schema: getParameterSchema(param),\n isRequired: param.required,\n isDisabled: isParamDisabled(param, example),\n originalParameter: param,\n } as TableRow\n },\n ),\n)\n\n// Generate a reverse map for fast lookup of headers by the name\nconst headersMap = computed(() =>\n groupBy(\n sections.value.header?.map((it) => ({\n ...it,\n name: it.name.toLowerCase(),\n })) ?? [],\n 'name',\n ),\n)\n\nconst defaultHeaders = computed(() => {\n const disableParameters =\n operation['x-scalar-disable-parameters']?.['default-headers']?.[\n exampleKey\n ] ?? {}\n\n const isOverridden = (name: string) => {\n const header = headersMap.value[name.toLowerCase()]?.[0]\n\n if (!header) {\n return false\n }\n\n return !header.isDisabled\n }\n\n return Object.entries(autoGeneratedHeaders).map(([name, value]) => {\n return {\n name,\n value,\n schema: undefined,\n isOverridden: isOverridden(name),\n isReadonly: true,\n isDisabled: disableParameters[name.toLowerCase()] ?? false,\n } satisfies TableRow\n })\n})\n\nconst headers = computed(() => [\n ...defaultHeaders.value,\n ...(sections.value.header ?? []),\n])\n\nconst defaultCookies = computed(() => {\n const environmentVariables = getEnvironmentVariables(environment)\n const resolvedUrl = getResolvedUrl({\n server,\n path,\n })\n const url = replaceEnvVariables(resolvedUrl, environmentVariables)\n\n const disabledGlobalCookies =\n operation['x-scalar-disable-parameters']?.['global-cookies']?.[\n exampleKey\n ] ?? {}\n\n const transform = (\n cookie: XScalarCookie,\n location: 'document' | 'workspace',\n ) => {\n return {\n name: cookie.name,\n value: cookie.value,\n globalRoute: { page: location, path: 'cookies' } as const,\n isReadonly: true,\n isDisabled: disabledGlobalCookies[cookie.name.toLowerCase()] ?? false,\n } satisfies TableRow\n }\n\n const globalCookies = [\n {\n location: 'workspace',\n cookies: workspaceCookies,\n },\n {\n location: 'document',\n cookies: documentCookies,\n },\n ] as const\n\n return globalCookies.flatMap(({ location, cookies }) => {\n return cookies\n .filter((cookie) =>\n filterGlobalCookie({\n cookie,\n url,\n disabledGlobalCookies: {},\n }),\n )\n .map((cookie) => transform(cookie, location))\n })\n})\n\nconst cookies = computed(() => [\n ...(defaultCookies.value ?? []),\n ...(sections.value.cookie ?? []),\n])\n\n/** Currently selected filter for the request sections */\nconst selectedFilter = ref<Filter>('All')\n\n/** Available operation sections */\nconst OPERATION_SECTIONS: readonly Filter[] = [\n 'Auth',\n 'Variables',\n 'Cookies',\n 'Headers',\n 'Query',\n 'Body',\n] as const\n\n/**\n * Pre-generated stable IDs for all possible filter sections.\n * These are created once at setup time to avoid regenerating IDs on re-render.\n */\nconst sectionIds: Record<Filter, string> = {\n All: useId(),\n Auth: useId(),\n Variables: useId(),\n Cookies: useId(),\n Headers: useId(),\n Query: useId(),\n Body: useId(),\n}\n\n/** Filters available based on operation state */\nconst filters = computed<Filter[]>(() => {\n const availableFilters = new Set<Filter>(['All', ...OPERATION_SECTIONS])\n\n if (!sections.value.path?.length) {\n availableFilters.delete('Variables')\n }\n if (!canMethodHaveBody(method)) {\n availableFilters.delete('Body')\n }\n if (isAuthHidden.value) {\n availableFilters.delete('Auth')\n }\n\n return [...availableFilters]\n})\n\n/**\n * Map available filters to their pre-generated stable IDs.\n * Only includes IDs for filters that are currently available.\n */\nconst filterIds = computed(\n () =>\n Object.fromEntries(\n filters.value.map((section) => [section, sectionIds[section]]),\n ) as Record<Filter, string>,\n)\n\n/**\n * Hide auth selector in readonly mode when no security schemes are defined.\n * This keeps the UI clean when there are no authentication options available.\n */\nconst isAuthHidden = computed(\n () => layout === 'modal' && !Object.keys(securitySchemes ?? {}).length,\n)\n\n/**\n * Keep auth available for unauthenticated operations, but collapse it by default\n * in readonly modal layouts unless a requirement or manual selection exists.\n */\nconst isAuthDefaultOpen = computed(\n () =>\n layout !== 'modal' ||\n Boolean(\n securityRequirements?.length || selectedSecurity.selectedSchemes.length,\n ),\n)\n\n/** Get a sensible placeholder for the request name input */\nconst requestNamePlaceholder = computed(() => {\n if (operation.summary) {\n return operation.summary\n }\n const cleanPath = path.replace(REGEX.PROTOCOL, '')\n return cleanPath || 'Request Name'\n})\n\n/** Check if the section should be shown based on the selected filter */\nconst isSectionVisible = (section: Filter): boolean => {\n return selectedFilter.value === 'All' || selectedFilter.value === section\n}\n\n/**\n * Reset filter to 'All' if Body filter is selected but method changes to one that cannot have a body.\n * This prevents showing an empty Body section when switching methods.\n */\nwatch(\n () => method,\n (newMethod) => {\n if (selectedFilter.value === 'Body' && !canMethodHaveBody(newMethod)) {\n selectedFilter.value = 'All'\n }\n },\n)\n\n/** Handle operation summary updates */\nconst handleSummaryUpdate = (event: Event): void => {\n const summary = (event.target as HTMLInputElement).value\n eventBus.emit('operation:update:meta', {\n meta: meta.value,\n payload: { summary: summary.trim() },\n })\n}\n\n/** Parameter handlers */\nconst parameterHandlers = computed(() => ({\n path: createParameterHandlers('path', eventBus, meta.value, {\n context: sections.value.path ?? [],\n }),\n cookie: createParameterHandlers('cookie', eventBus, meta.value, {\n context: cookies.value ?? [],\n globalParameters: defaultCookies.value.length,\n }),\n header: createParameterHandlers('header', eventBus, meta.value, {\n context: headers.value,\n defaultParameters: defaultHeaders.value.length,\n }),\n query: createParameterHandlers('query', eventBus, meta.value, {\n context: sections.value.query ?? [],\n }),\n}))\n\n/** Handle request body content type update */\nconst handleUpdateContentType = (payload: { value: string }): void =>\n eventBus.emit('operation:update:requestBody:contentType', {\n payload: { contentType: payload.value },\n meta: meta.value,\n })\n\n/** Handle request body value update */\nconst handleUpdateBodyValue = ({\n payload,\n contentType,\n}: Pick<\n ApiReferenceEvents['operation:update:requestBody:value'],\n 'payload' | 'contentType'\n>): void => {\n const debounceKey =\n typeof payload === 'string'\n ? `update:requestBody:value-${contentType}`\n : undefined\n\n eventBus.emit(\n 'operation:update:requestBody:value',\n {\n payload,\n contentType,\n meta: meta.value,\n },\n {\n debounceKey,\n },\n )\n}\n\n/** Handle request body value update */\nconst handleUpdateBodyFormValue = ({\n payload,\n contentType,\n}: Pick<\n ApiReferenceEvents['operation:update:requestBody:formValue'],\n 'payload' | 'contentType'\n>): void => {\n const debounceKey = `update:requestBody:${contentType}-form-value`\n\n eventBus.emit(\n 'operation:update:requestBody:formValue',\n {\n payload: payload.map((row) => unpackProxyObject(row, { depth: 1 })),\n contentType,\n meta: meta.value,\n },\n {\n debounceKey,\n },\n )\n}\n\nconst labelRequestNameId = useId()\n\nconst globalCookies = computed(() => [...workspaceCookies, ...documentCookies])\n\n/** Allow updating the operation extensions for the plugins */\nconst updateOperationExtension = (\n payload: ApiReferenceEvents['operation:update:extension']['payload'],\n): void =>\n eventBus.emit('operation:update:extension', { payload, meta: meta.value })\n</script>\n<template>\n <ViewLayoutSection :aria-label=\"`Request: ${operation.summary}`\">\n <template #title>\n <div\n class=\"group pointer-events-none flex flex-1 items-center gap-1 lg:pr-24\">\n <label\n v-if=\"layout !== 'modal'\"\n class=\"pointer-events-auto absolute top-0 left-0 h-full w-full cursor-text opacity-0\"\n :for=\"labelRequestNameId\" />\n <input\n v-if=\"layout !== 'modal'\"\n :id=\"labelRequestNameId\"\n class=\"text-c-1 group-hover-input pointer-events-auto relative z-10 -ml-0.5 h-8 w-full rounded pl-1.25 has-[:focus-visible]:outline md:-ml-1.25\"\n :placeholder=\"requestNamePlaceholder\"\n :value=\"operation.summary\"\n @blur=\"handleSummaryUpdate\" />\n <span\n v-else\n class=\"text-c-1 flex h-8 items-center\">\n {{ operation.summary }}\n </span>\n </div>\n <SectionFilter\n v-model=\"selectedFilter\"\n :filterIds=\"filterIds\"\n :filters=\"filters\" />\n </template>\n\n <div\n :id=\"filterIds.All\"\n class=\"request-section-content custom-scroll relative flex flex-1 flex-col\"\n :role=\"selectedFilter === 'All' ? 'tabpanel' : 'none'\">\n <!-- Auth Selector -->\n <AuthSelector\n v-show=\"isSectionVisible('Auth') && !isAuthHidden\"\n :id=\"filterIds.Auth\"\n :createAnySecurityScheme=\"layout !== 'modal'\"\n :defaultOpen=\"isAuthDefaultOpen\"\n :environment\n :eventBus\n :meta=\"authMeta\"\n :options\n :proxyUrl\n :securityRequirements\n :securitySchemes\n :selectedSecurity\n :selectedSecuritySchemes\n :server\n title=\"Authentication\" />\n\n <!-- Variables (Path Parameters) -->\n <RequestParams\n v-show=\"isSectionVisible('Variables') && sections.path?.length\"\n :id=\"filterIds.Variables\"\n :environment\n :eventBus\n :exampleKey\n :rows=\"sections.path ?? []\"\n :showAddRowPlaceholder=\"false\"\n title=\"Variables\"\n v-on=\"parameterHandlers.path\" />\n\n <!-- Cookies -->\n <RequestParams\n v-show=\"isSectionVisible('Cookies')\"\n :id=\"filterIds.Cookies\"\n :environment\n :eventBus\n :exampleKey\n :rows=\"cookies ?? []\"\n :showAddRowPlaceholder=\"true\"\n title=\"Cookies\"\n v-on=\"parameterHandlers.cookie\" />\n\n <!-- Headers -->\n <RequestParams\n v-show=\"isSectionVisible('Headers')\"\n :id=\"filterIds.Headers\"\n :environment\n :eventBus\n :exampleKey\n :rows=\"headers ?? []\"\n title=\"Headers\"\n v-on=\"parameterHandlers.header\" />\n\n <!-- Query Parameters -->\n <RequestParams\n v-show=\"isSectionVisible('Query')\"\n :id=\"filterIds.Query\"\n :environment\n :eventBus\n :exampleKey\n :rows=\"sections.query ?? []\"\n title=\"Query Parameters\"\n v-on=\"parameterHandlers.query\" />\n\n <!-- Request Body -->\n <RequestBody\n v-show=\"isSectionVisible('Body') && canMethodHaveBody(method)\"\n :id=\"filterIds.Body\"\n :environment\n :exampleKey\n :requestBody=\"getResolvedRef(operation.requestBody)\"\n :requestBodyCompositionSelection\n title=\"Request Body\"\n @update:contentType=\"handleUpdateContentType\"\n @update:formValue=\"handleUpdateBodyFormValue\"\n @update:value=\"handleUpdateBodyValue\" />\n\n <!-- Inject request section plugin components -->\n <ScalarErrorBoundary\n v-for=\"(plugin, index) in plugins\"\n :key=\"index\">\n <component\n :is=\"plugin.components.request.component\"\n v-if=\"plugin?.components?.request\"\n v-show=\"selectedFilter === 'All'\"\n :operation\n v-bind=\"plugin.components.request.additionalProps\"\n @operation:update:extension=\"updateOperationExtension\" />\n </ScalarErrorBoundary>\n\n <!-- Spacer -->\n <div class=\"flex grow\" />\n <!-- Code Snippet -->\n <RequestCodeSnippet\n v-show=\"selectedFilter === 'All'\"\n :clientOptions\n :eventBus\n :globalCookies\n integration=\"client\"\n :method\n :operation\n :path\n :securitySchemes=\"selectedSecuritySchemes\"\n :selectedClient\n :selectedContentType=\"\n getResolvedRef(operation.requestBody)?.[\n 'x-scalar-selected-content-type'\n ]?.[exampleKey]\n \"\n :selectedServer=\"server ?? undefined\" />\n </div>\n </ViewLayoutSection>\n</template>\n<style scoped>\n.request-section-content {\n --scalar-border-width: 0.5px;\n}\n.request-section-content-filter {\n box-shadow: 0 -10px 0 10px var(--scalar-background-1);\n}\n.request-item:focus-within .request-meta-buttons {\n opacity: 1;\n}\n.group-hover-input {\n border-width: var(--scalar-border-width);\n border-color: transparent;\n}\n.group:hover .group-hover-input {\n background: color-mix(\n in srgb,\n var(--scalar-background-1),\n var(--scalar-background-2)\n );\n border-color: var(--scalar-border-color);\n}\n.group-hover-input:focus {\n background: transparent !important;\n border-color: var(--scalar-border-color) !important;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4GA,MAAM,OAAO,gBAAgB;GAC3B,QAAK,QAAA;GACL,MAAG,QAAA;GACH,YAAS,QAAA;GACV,EAAC;;EAGF,MAAM,WAAW,eACf,QACE,QAAA,UAAU,YAAY,KAAK,UAAU,eAAe,MAAM,CAAC,IAAI,EAAE,EACjE,OACC,UAAU;GACT,MAAM,UAAU,WAAW,OAAO,QAAA,YAAY,KAAA,EAAS;AAEvD,UAAO;IACL,MAAM,MAAM;IACZ,OAAO,SAAS,SAAS;IACzB,aAAa,MAAM;IACnB,QAAQ,mBAAmB,MAAM;IACjC,YAAY,MAAM;IAClB,YAAY,gBAAgB,OAAO,QAAQ;IAC3C,mBAAmB;IACpB;IAEJ,CACH;EAGA,MAAM,aAAa,eACjB,QACE,SAAS,MAAM,QAAQ,KAAK,QAAQ;GAClC,GAAG;GACH,MAAM,GAAG,KAAK,aAAa;GAC5B,EAAE,IAAI,EAAE,EACT,OACD,CACH;EAEA,MAAM,iBAAiB,eAAe;GACpC,MAAM,oBACJ,QAAA,UAAU,iCAAiC,qBACzC,QAAA,eACG,EAAC;GAER,MAAM,gBAAgB,SAAiB;IACrC,MAAM,SAAS,WAAW,MAAM,KAAK,aAAa,IAAI;AAEtD,QAAI,CAAC,OACH,QAAO;AAGT,WAAO,CAAC,OAAO;;AAGjB,UAAO,OAAO,QAAQ,QAAA,eAAqB,CAAC,KAAK,CAAC,MAAM,WAAW;AACjE,WAAO;KACL;KACA;KACA,QAAQ,KAAA;KACR,cAAc,aAAa,KAAK;KAChC,YAAY;KACZ,YAAY,kBAAkB,KAAK,aAAa,KAAK;KACtD;KACF;IACF;EAED,MAAM,UAAU,eAAe,CAC7B,GAAG,eAAe,OAClB,GAAI,SAAS,MAAM,UAAU,EAAE,CAChC,CAAA;EAED,MAAM,iBAAiB,eAAe;GACpC,MAAM,uBAAuB,wBAAwB,QAAA,YAAW;GAKhE,MAAM,MAAM,oBAJQ,eAAe;IACjC,QAAK,QAAA;IACL,MAAG,QAAA;IACJ,CAAA,EAC4C,qBAAoB;GAEjE,MAAM,wBACJ,QAAA,UAAU,iCAAiC,oBACzC,QAAA,eACG,EAAC;GAER,MAAM,aACJ,QACA,aACG;AACH,WAAO;KACL,MAAM,OAAO;KACb,OAAO,OAAO;KACd,aAAa;MAAE,MAAM;MAAU,MAAM;MAAW;KAChD,YAAY;KACZ,YAAY,sBAAsB,OAAO,KAAK,aAAa,KAAK;KACjE;;AAcH,UAXsB,CACpB;IACE,UAAU;IACV,SAAS,QAAA;IACV,EACD;IACE,UAAU;IACV,SAAS,QAAA;IACV,CACF,CAEoB,SAAS,EAAE,UAAU,cAAc;AACtD,WAAO,QACJ,QAAQ,WACP,mBAAmB;KACjB;KACA;KACA,uBAAuB,EAAE;KAC1B,CAAC,CACJ,CACC,KAAK,WAAW,UAAU,QAAQ,SAAS,CAAA;KAC/C;IACF;EAED,MAAM,UAAU,eAAe,CAC7B,GAAI,eAAe,SAAS,EAAE,EAC9B,GAAI,SAAS,MAAM,UAAU,EAAE,CAChC,CAAA;;EAGD,MAAM,iBAAiB,IAAY,MAAK;;EAGxC,MAAM,qBAAwC;GAC5C;GACA;GACA;GACA;GACA;GACA;GACD;;;;;EAMD,MAAM,aAAqC;GACzC,KAAK,OAAO;GACZ,MAAM,OAAO;GACb,WAAW,OAAO;GAClB,SAAS,OAAO;GAChB,SAAS,OAAO;GAChB,OAAO,OAAO;GACd,MAAM,OAAO;GACf;;EAGA,MAAM,UAAU,eAAyB;GACvC,MAAM,mBAAmB,IAAI,IAAY,CAAC,OAAO,GAAG,mBAAmB,CAAA;AAEvE,OAAI,CAAC,SAAS,MAAM,MAAM,OACxB,kBAAiB,OAAO,YAAW;AAErC,OAAI,CAAC,kBAAkB,QAAA,OAAO,CAC5B,kBAAiB,OAAO,OAAM;AAEhC,OAAI,aAAa,MACf,kBAAiB,OAAO,OAAM;AAGhC,UAAO,CAAC,GAAG,iBAAgB;IAC5B;;;;;EAMD,MAAM,YAAY,eAEd,OAAO,YACL,QAAQ,MAAM,KAAK,YAAY,CAAC,SAAS,WAAW,SAAS,CAAC,CAC/D,CACL;;;;;EAMA,MAAM,eAAe,eACb,QAAA,WAAW,WAAW,CAAC,OAAO,KAAK,QAAA,mBAAmB,EAAE,CAAC,CAAC,OAClE;;;;;EAMA,MAAM,oBAAoB,eAEtB,QAAA,WAAW,WACX,QACE,QAAA,sBAAsB,UAAU,QAAA,iBAAiB,gBAAgB,OAClE,CACL;;EAGA,MAAM,yBAAyB,eAAe;AAC5C,OAAI,QAAA,UAAU,QACZ,QAAO,QAAA,UAAU;AAGnB,UADkB,QAAA,KAAK,QAAQ,MAAM,UAAU,GAAE,IAC7B;IACrB;;EAGD,MAAM,oBAAoB,YAA6B;AACrD,UAAO,eAAe,UAAU,SAAS,eAAe,UAAU;;;;;;AAOpE,cACQ,QAAA,SACL,cAAc;AACb,OAAI,eAAe,UAAU,UAAU,CAAC,kBAAkB,UAAU,CAClE,gBAAe,QAAQ;IAG7B;;EAGA,MAAM,uBAAuB,UAAuB;GAClD,MAAM,UAAW,MAAM,OAA4B;AACnD,WAAA,SAAS,KAAK,yBAAyB;IACrC,MAAM,KAAK;IACX,SAAS,EAAE,SAAS,QAAQ,MAAM,EAAE;IACrC,CAAA;;;EAIH,MAAM,oBAAoB,gBAAgB;GACxC,MAAM,wBAAwB,QAAQ,QAAA,UAAU,KAAK,OAAO,EAC1D,SAAS,SAAS,MAAM,QAAQ,EAAE,EACnC,CAAC;GACF,QAAQ,wBAAwB,UAAU,QAAA,UAAU,KAAK,OAAO;IAC9D,SAAS,QAAQ,SAAS,EAAE;IAC5B,kBAAkB,eAAe,MAAM;IACxC,CAAC;GACF,QAAQ,wBAAwB,UAAU,QAAA,UAAU,KAAK,OAAO;IAC9D,SAAS,QAAQ;IACjB,mBAAmB,eAAe,MAAM;IACzC,CAAC;GACF,OAAO,wBAAwB,SAAS,QAAA,UAAU,KAAK,OAAO,EAC5D,SAAS,SAAS,MAAM,SAAS,EAAE,EACpC,CAAC;GACH,EAAC;;EAGF,MAAM,2BAA2B,YAC/B,QAAA,SAAS,KAAK,4CAA4C;GACxD,SAAS,EAAE,aAAa,QAAQ,OAAO;GACvC,MAAM,KAAK;GACZ,CAAA;;EAGH,MAAM,yBAAyB,EAC7B,SACA,kBAIU;GACV,MAAM,cACJ,OAAO,YAAY,WACf,4BAA4B,gBAC5B,KAAA;AAEN,WAAA,SAAS,KACP,sCACA;IACE;IACA;IACA,MAAM,KAAK;IACZ,EACD,EACE,aACD,CACH;;;EAIF,MAAM,6BAA6B,EACjC,SACA,kBAIU;GACV,MAAM,cAAc,sBAAsB,YAAY;AAEtD,WAAA,SAAS,KACP,0CACA;IACE,SAAS,QAAQ,KAAK,QAAQ,kBAAkB,KAAK,EAAE,OAAO,GAAG,CAAC,CAAC;IACnE;IACA,MAAM,KAAK;IACZ,EACD,EACE,aACD,CACH;;EAGF,MAAM,qBAAqB,OAAM;EAEjC,MAAM,gBAAgB,eAAe,CAAC,GAAG,QAAA,kBAAkB,GAAG,QAAA,gBAAgB,CAAA;;EAG9E,MAAM,4BACJ,YAEA,QAAA,SAAS,KAAK,8BAA8B;GAAE;GAAS,MAAM,KAAK;GAAO,CAAA;;uBAGzE,YA8IoB,2BAAA,EA9IA,cAAU,YAAc,QAAA,UAAU,WAAA,EAAA;IACzC,OAAK,cAmBR,CAlBN,mBAkBM,OAlBN,YAkBM,CAfI,QAAA,WAAM,WAAA,WAAA,EADd,mBAG8B,SAAA;;KAD5B,OAAM;KACL,KAAK,MAAA,mBAAkB;6DAElB,QAAA,WAAM,WAAA,WAAA,EADd,mBAMgC,SAAA;;KAJ7B,IAAI,MAAA,mBAAkB;KACvB,OAAM;KACL,aAAa,uBAAA;KACb,OAAO,QAAA,UAAU;KACjB,QAAM;8CACT,mBAIO,QAJP,YAIO,gBADF,QAAA,UAAU,QAAO,EAAA,EAAA,EAAA,CAAA,EAGxB,YAGuB,uBAAA;iBAFZ,eAAA;iFAAc,QAAA;KACtB,WAAW,UAAA;KACX,SAAS,QAAA;;;;;;2BAqHR,CAlHN,mBAkHM,OAAA;KAjHH,IAAI,UAAA,MAAU;KACf,OAAM;KACL,MAAM,eAAA,UAAc,QAAA,aAAA;;oBAErB,YAe2B,MAAA,qBAAA,EAAA;MAbxB,IAAI,UAAA,MAAU;MACd,yBAAyB,QAAA,WAAM;MAC/B,aAAa,kBAAA;MACb,aAAA,QAAA;MACA,UAAA,QAAA;MACA,MAAM,QAAA;MACN,SAAA,QAAA;MACA,UAAA,QAAA;MACA,sBAAA,QAAA;MACA,iBAAA,QAAA;MACA,kBAAA,QAAA;MACA,yBAAA,QAAA;MACA,QAAA,QAAA;MACD,OAAM;;;;;;;;;;;;;;;kBAdE,iBAAgB,OAAA,IAAA,CAAa,aAAA,MAAY,CAAA,CAAA;oBAiBnD,YASkC,uBATlC,WASkC;MAP/B,IAAI,UAAA,MAAU;MACd,aAAA,QAAA;MACA,UAAA,QAAA;MACA,YAAA,QAAA;MACA,MAAM,SAAA,MAAS,QAAI,EAAA;MACnB,uBAAuB;MACxB,OAAM;QACN,WAAM,kBAAuB,MAAL,KAAI,CAAA,EAAA,MAAA,IAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA,CAAA,EAAA,CAAA,CAAA,OARpB,iBAAgB,YAAA,IAAiB,SAAA,MAAS,MAAM,OAAM,CAAA,CAAA;oBAWhE,YASoC,uBATpC,WASoC;MAPjC,IAAI,UAAA,MAAU;MACd,aAAA,QAAA;MACA,UAAA,QAAA;MACA,YAAA,QAAA;MACA,MAAM,QAAA,SAAO,EAAA;MACb,uBAAuB;MACxB,OAAM;QACN,WAAM,kBAAyB,MAAP,OAAM,CAAA,EAAA,MAAA,IAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA,CAAA,EAAA,CAAA,CAAA,OARtB,iBAAgB,UAAA,CAAA,CAAA,CAAA;oBAW1B,YAQoC,uBARpC,WAQoC;MANjC,IAAI,UAAA,MAAU;MACd,aAAA,QAAA;MACA,UAAA,QAAA;MACA,YAAA,QAAA;MACA,MAAM,QAAA,SAAO,EAAA;MACd,OAAM;QACN,WAAM,kBAAyB,MAAP,OAAM,CAAA,EAAA,MAAA,IAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA,CAAA,EAAA,CAAA,CAAA,OAPtB,iBAAgB,UAAA,CAAA,CAAA,CAAA;oBAU1B,YAQmC,uBARnC,WAQmC;MANhC,IAAI,UAAA,MAAU;MACd,aAAA,QAAA;MACA,UAAA,QAAA;MACA,YAAA,QAAA;MACA,MAAM,SAAA,MAAS,SAAK,EAAA;MACrB,OAAM;QACN,WAAM,kBAAwB,MAAN,MAAK,CAAA,EAAA,MAAA,IAAA;MAAA;MAAA;MAAA;MAAA;MAAA;MAAA,CAAA,EAAA,CAAA,CAAA,OAPrB,iBAAgB,QAAA,CAAA,CAAA,CAAA;oBAU1B,YAU0C,qBAAA;MARvC,IAAI,UAAA,MAAU;MACd,aAAA,QAAA;MACA,YAAA,QAAA;MACA,aAAa,MAAA,eAAc,CAAC,QAAA,UAAU,YAAW;MACjD,iCAAA,QAAA;MACD,OAAM;MACL,wBAAoB;MACpB,sBAAkB;MAClB,kBAAc;;;;;;;kBATP,iBAAgB,OAAA,IAAY,MAAA,kBAAiB,CAAC,QAAA,OAAM,CAAA,CAAA,CAAA;uBAY9D,mBAUsB,UAAA,MAAA,WATM,QAAA,UAAlB,QAAQ,UAAK;0BADvB,YAUsB,MAAA,oBAAA,EAAA,EARnB,KAAK,OAAK,EAAA;8BAOgD,CAJnD,QAAQ,YAAY,UAAA,gBAAA,WAAA,EAF5B,YAM2D,wBALpD,OAAO,WAAW,QAAQ,UAAS,EAD1C,WAM2D;;QAFxD,WAAA,QAAA;6BACO,OAAO,WAAW,QAAQ,iBAAe,EAChD,gCAA4B,0BAAwB,CAAA,EAAA,MAAA,IAAA,CAAA,YAAA,CAAA,GAAA,CAAA,CAAA,OAH7C,eAAA,UAAc,MAAA,CAAA,CAAA,GAAA,mBAAA,IAAA,KAAA,CAAA,CAAA;;;;+BAO1B,mBAAyB,OAAA,EAApB,OAAM,aAAW,EAAA,MAAA,GAAA;oBAEtB,YAgB0C,4BAAA;MAdvC,eAAA,QAAA;MACA,UAAA,QAAA;MACA,eAAA,cAAA;MACD,aAAY;MACX,QAAA,QAAA;MACA,WAAA,QAAA;MACA,MAAA,QAAA;MACA,iBAAiB,QAAA;MACjB,gBAAA,QAAA;MACA,qBAAgC,MAAA,eAAc,CAAC,QAAA,UAAU,YAAW,GAAA,oCAAgE,QAAA;MAKpI,gBAAgB,QAAA,UAAU,KAAA;;;;;;;;;;;;kBAfnB,eAAA,UAAc,MAAA,CAAA,CAAA"}

@@ -35,3 +35,3 @@ import type { HttpMethod as HttpMethodType } from '@scalar/helpers/http/http-methods';

declare const __VLS_export: import("vue").DefineComponent<AddressBarProps, {
methodConflict: import("vue").Ref<"delete" | "head" | "get" | "options" | "put" | "post" | "patch" | "trace" | null, "delete" | "head" | "get" | "options" | "put" | "post" | "patch" | "trace" | null>;
methodConflict: import("vue").Ref<"head" | "delete" | "get" | "options" | "patch" | "post" | "put" | "trace" | null, "head" | "delete" | "get" | "options" | "patch" | "post" | "put" | "trace" | null>;
pathConflict: import("vue").Ref<string | null, string | null>;

@@ -38,0 +38,0 @@ }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {

@@ -1,1 +0,1 @@

{"version":3,"file":"EnvironmentSelector.vue.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarDropdown,\n ScalarDropdownDivider,\n ScalarDropdownItem,\n ScalarIcon,\n} from '@scalar/components'\nimport { computed } from 'vue'\n\nconst { environments = [], activeEnvironment } = defineProps<{\n /** List of available environments */\n environments?: string[]\n /** Currently selected environment */\n activeEnvironment?: string\n}>()\n\nconst emit = defineEmits<{\n /** Emitted when an environment is selected */\n (e: 'select:environment', environmentName: string): void\n /** Emitted when user wants to add a new environment */\n (e: 'add:environment'): void\n}>()\n\n/** Whether an environment is currently active */\nconst hasActiveEnvironment = computed(() => !!activeEnvironment)\n\n/** Whether environments exist */\nconst hasEnvironments = computed(() => environments.length > 0)\n\n/** Whether the currently selected environment exists in the dropdown options */\nconst hasSelectedEnvironmentInOptions = computed(() => {\n if (!activeEnvironment) {\n return false\n }\n\n return environments.includes(activeEnvironment)\n})\n\n/** True when an environment is selected but unavailable in the current context */\nconst hasMissingActiveEnvironment = computed(\n () => hasActiveEnvironment.value && !hasSelectedEnvironmentInOptions.value,\n)\n\n/** Display text for the button */\nconst displayText = computed(() => {\n if (hasMissingActiveEnvironment.value) {\n return `${activeEnvironment} (Unavailable)`\n }\n\n if (hasActiveEnvironment.value) {\n return activeEnvironment\n }\n if (!hasEnvironments.value) {\n return 'Add Environment'\n }\n return 'Select Environment'\n})\n\n/** Button styling based on state */\nconst buttonClass = computed(() => {\n if (hasMissingActiveEnvironment.value) {\n return 'hover:bg-b-2 text-c-2 border-transparent'\n }\n\n if (hasActiveEnvironment.value) {\n return 'bg-c-accent/10 text-c-accent hover:bg-c-accent/20 border-c-accent/30'\n }\n if (!hasEnvironments.value) {\n return 'hover:bg-b-2 text-c-3 border-transparent'\n }\n return 'hover:bg-b-2 text-c-2 border-transparent'\n})\n\nconst handleAddEnvironment = () => {\n emit('add:environment')\n}\n\nconst handleSelectEnvironment = (environmentName: string) => {\n emit('select:environment', environmentName)\n}\n</script>\n\n<template>\n <div class=\"relative flex items-center\">\n <!-- Environment indicator badge (only show when active) -->\n\n <ScalarDropdown>\n <ScalarButton\n :aria-label=\"`Current environment: ${displayText}`\"\n class=\"line-clamp-1 h-full w-fit justify-start border px-2 py-1 font-normal transition-colors\"\n :class=\"buttonClass\"\n size=\"sm\"\n variant=\"ghost\">\n <div class=\"flex max-w-[220px] min-w-0 items-center gap-1.5\">\n <!-- Icon indicator -->\n <ScalarIcon\n class=\"shrink-0\"\n :class=\"\n hasActiveEnvironment && !hasMissingActiveEnvironment\n ? 'text-c-accent'\n : 'text-c-3'\n \"\n icon=\"Globe\"\n size=\"sm\" />\n\n <!-- Environment name -->\n <span\n class=\"text-xxs block max-w-[160px] min-w-0 truncate text-left font-medium\">\n {{ displayText }}\n </span>\n\n <!-- Dropdown arrow -->\n <ScalarIcon\n class=\"shrink-0\"\n icon=\"ChevronDown\"\n size=\"xs\" />\n </div>\n </ScalarButton>\n\n <template #items>\n <!-- No environment option (clear selection) -->\n <ScalarDropdownItem\n v-if=\"hasActiveEnvironment\"\n class=\"group/item flex w-full items-center gap-1.5\"\n @click.stop=\"handleSelectEnvironment('')\">\n <div\n class=\"flex h-4 w-4 items-center justify-center rounded-full p-[3px]\"\n :class=\"\n !activeEnvironment\n ? 'bg-c-accent text-b-1'\n : 'shadow-border text-transparent'\n \">\n <ScalarIcon\n class=\"size-2.5\"\n icon=\"Checkmark\"\n thickness=\"3\" />\n </div>\n <span class=\"text-c-2\">No Environment</span>\n </ScalarDropdownItem>\n\n <ScalarDropdownDivider v-if=\"hasActiveEnvironment && hasEnvironments\" />\n\n <!-- Environment list -->\n <ScalarDropdownItem\n v-for=\"environmentName in environments\"\n :key=\"environmentName\"\n class=\"group/item flex w-full min-w-0 items-center gap-1.5 overflow-hidden text-ellipsis whitespace-nowrap\"\n @click.stop=\"handleSelectEnvironment(environmentName)\">\n <div\n class=\"flex h-4 w-4 items-center justify-center rounded-full p-[3px]\"\n :class=\"\n activeEnvironment === environmentName\n ? 'bg-c-accent text-b-1'\n : 'shadow-border text-transparent'\n \">\n <ScalarIcon\n class=\"size-2.5\"\n icon=\"Checkmark\"\n thickness=\"3\" />\n </div>\n <span class=\"min-w-0 flex-1 truncate\">{{ environmentName }}</span>\n </ScalarDropdownItem>\n <ScalarDropdownDivider v-if=\"hasMissingActiveEnvironment\" />\n\n <ScalarDropdownItem\n v-if=\"hasMissingActiveEnvironment\"\n class=\"group/item flex h-auto w-full min-w-0 items-start gap-1.5 overflow-hidden\"\n disabled>\n <div\n class=\"bg-c-accent text-b-1 mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full p-[3px]\">\n <ScalarIcon\n class=\"size-2.5\"\n icon=\"Checkmark\"\n thickness=\"3\" />\n </div>\n <div class=\"min-w-0 flex-1 text-left\">\n <span class=\"block truncate\">\n {{ activeEnvironment }}\n </span>\n <span class=\"text-c-3 block truncate text-xs\">\n Not available in this context\n </span>\n </div>\n </ScalarDropdownItem>\n\n <ScalarDropdownDivider v-if=\"hasEnvironments\" />\n\n <!-- Add new environment button -->\n <ScalarDropdownItem\n class=\"text-c-accent flex items-center gap-1.5\"\n @click=\"handleAddEnvironment\">\n <div class=\"flex h-4 w-4 items-center justify-center\">\n <ScalarIcon\n icon=\"Add\"\n size=\"sm\" />\n </div>\n <span>{{\n hasEnvironments ? 'New Environment' : 'Create Environment'\n }}</span>\n </ScalarDropdownItem>\n\n <!-- Helper text for empty state -->\n <div\n v-if=\"!hasEnvironments && !hasActiveEnvironment\"\n class=\"text-c-3 px-2 py-1.5 text-xs\">\n <p class=\"mb-1\">\n Environments let you manage variables like API keys and base URLs\n across different contexts.\n </p>\n </div>\n </template>\n </ScalarDropdown>\n </div>\n</template>\n"],"mappings":""}
{"version":3,"file":"EnvironmentSelector.vue.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarDropdown,\n ScalarDropdownDivider,\n ScalarDropdownItem,\n ScalarIcon,\n} from '@scalar/components'\nimport { computed } from 'vue'\n\nconst { environments = [], activeEnvironment } = defineProps<{\n /** List of available environments */\n environments?: string[]\n /** Currently selected environment */\n activeEnvironment?: string\n}>()\n\nconst emit = defineEmits<{\n /** Emitted when an environment is selected */\n (e: 'select:environment', environmentName: string): void\n /** Emitted when user wants to add a new environment */\n (e: 'add:environment'): void\n}>()\n\n/** Whether an environment is currently active */\nconst hasActiveEnvironment = computed(() => !!activeEnvironment)\n\n/** Whether environments exist */\nconst hasEnvironments = computed(() => environments.length > 0)\n\n/** Whether the currently selected environment exists in the dropdown options */\nconst hasSelectedEnvironmentInOptions = computed(() => {\n if (!activeEnvironment) {\n return false\n }\n\n return environments.includes(activeEnvironment)\n})\n\n/** True when an environment is selected but unavailable in the current context */\nconst hasMissingActiveEnvironment = computed(\n () => hasActiveEnvironment.value && !hasSelectedEnvironmentInOptions.value,\n)\n\n/** Display text for the button */\nconst displayText = computed(() => {\n if (hasMissingActiveEnvironment.value) {\n return `${activeEnvironment} (Unavailable)`\n }\n\n if (hasActiveEnvironment.value) {\n return activeEnvironment\n }\n if (!hasEnvironments.value) {\n return 'Add Environment'\n }\n return 'Select Environment'\n})\n\n/** Button styling based on state */\nconst buttonClass = computed(() => {\n if (hasMissingActiveEnvironment.value) {\n return 'hover:bg-b-2 text-c-2 border-transparent'\n }\n\n if (hasActiveEnvironment.value) {\n return 'bg-c-accent/10 text-c-accent hover:bg-c-accent/20 border-c-accent/30'\n }\n if (!hasEnvironments.value) {\n return 'hover:bg-b-2 text-c-3 border-transparent'\n }\n return 'hover:bg-b-2 text-c-2 border-transparent'\n})\n\nconst handleAddEnvironment = () => {\n emit('add:environment')\n}\n\nconst handleSelectEnvironment = (environmentName: string) => {\n emit('select:environment', environmentName)\n}\n</script>\n\n<template>\n <div class=\"relative flex items-center\">\n <!-- Environment indicator badge (only show when active) -->\n\n <ScalarDropdown>\n <ScalarButton\n :aria-label=\"`Current environment: ${displayText}`\"\n class=\"line-clamp-1 h-full w-fit justify-start border px-2 py-1 font-normal transition-colors\"\n :class=\"buttonClass\"\n size=\"sm\"\n variant=\"ghost\">\n <div class=\"flex max-w-[220px] min-w-0 items-center gap-1.5\">\n <!-- Icon indicator -->\n <ScalarIcon\n class=\"shrink-0\"\n :class=\"\n hasActiveEnvironment && !hasMissingActiveEnvironment\n ? 'text-c-accent'\n : 'text-c-3'\n \"\n icon=\"Globe\"\n size=\"sm\" />\n\n <!-- Environment name -->\n <span\n class=\"text-xxs block max-w-[160px] min-w-0 truncate text-left font-medium\">\n {{ displayText }}\n </span>\n\n <!-- Dropdown arrow -->\n <ScalarIcon\n class=\"shrink-0\"\n icon=\"ChevronDown\"\n size=\"xs\" />\n </div>\n </ScalarButton>\n\n <template #items>\n <!-- No environment option (clear selection) -->\n <ScalarDropdownItem\n v-if=\"hasActiveEnvironment\"\n class=\"group/item flex w-full items-center gap-1.5\"\n @click=\"handleSelectEnvironment('')\">\n <div\n class=\"flex h-4 w-4 items-center justify-center rounded-full p-[3px]\"\n :class=\"\n !activeEnvironment\n ? 'bg-c-accent text-b-1'\n : 'shadow-border text-transparent'\n \">\n <ScalarIcon\n class=\"size-2.5\"\n icon=\"Checkmark\"\n thickness=\"3\" />\n </div>\n <span class=\"text-c-2\">No Environment</span>\n </ScalarDropdownItem>\n\n <ScalarDropdownDivider v-if=\"hasActiveEnvironment && hasEnvironments\" />\n\n <!-- Environment list -->\n <ScalarDropdownItem\n v-for=\"environmentName in environments\"\n :key=\"environmentName\"\n class=\"group/item flex w-full min-w-0 items-center gap-1.5 overflow-hidden text-ellipsis whitespace-nowrap\"\n @click=\"handleSelectEnvironment(environmentName)\">\n <div\n class=\"flex h-4 w-4 items-center justify-center rounded-full p-[3px]\"\n :class=\"\n activeEnvironment === environmentName\n ? 'bg-c-accent text-b-1'\n : 'shadow-border text-transparent'\n \">\n <ScalarIcon\n class=\"size-2.5\"\n icon=\"Checkmark\"\n thickness=\"3\" />\n </div>\n <span class=\"min-w-0 flex-1 truncate\">{{ environmentName }}</span>\n </ScalarDropdownItem>\n <ScalarDropdownDivider v-if=\"hasMissingActiveEnvironment\" />\n\n <ScalarDropdownItem\n v-if=\"hasMissingActiveEnvironment\"\n class=\"group/item flex h-auto w-full min-w-0 items-start gap-1.5 overflow-hidden\"\n disabled>\n <div\n class=\"bg-c-accent text-b-1 mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full p-[3px]\">\n <ScalarIcon\n class=\"size-2.5\"\n icon=\"Checkmark\"\n thickness=\"3\" />\n </div>\n <div class=\"min-w-0 flex-1 text-left\">\n <span class=\"block truncate\">\n {{ activeEnvironment }}\n </span>\n <span class=\"text-c-3 block truncate text-xs\">\n Not available in this context\n </span>\n </div>\n </ScalarDropdownItem>\n\n <ScalarDropdownDivider v-if=\"hasEnvironments\" />\n\n <!-- Add new environment button -->\n <ScalarDropdownItem\n class=\"text-c-accent flex items-center gap-1.5\"\n @click=\"handleAddEnvironment\">\n <div class=\"flex h-4 w-4 items-center justify-center\">\n <ScalarIcon\n icon=\"Add\"\n size=\"sm\" />\n </div>\n <span>{{\n hasEnvironments ? 'New Environment' : 'Create Environment'\n }}</span>\n </ScalarDropdownItem>\n\n <!-- Helper text for empty state -->\n <div\n v-if=\"!hasEnvironments && !hasActiveEnvironment\"\n class=\"text-c-3 px-2 py-1.5 text-xs\">\n <p class=\"mb-1\">\n Environments let you manage variables like API keys and base URLs\n across different contexts.\n </p>\n </div>\n </template>\n </ScalarDropdown>\n </div>\n</template>\n"],"mappings":""}

@@ -1,2 +0,2 @@

import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, normalizeClass, openBlock, renderList, toDisplayString, unref, withCtx, withModifiers } from "vue";
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, normalizeClass, openBlock, renderList, toDisplayString, unref, withCtx } from "vue";
import { ScalarButton, ScalarDropdown, ScalarDropdownDivider, ScalarDropdownItem, ScalarIcon } from "@scalar/components";

@@ -62,3 +62,3 @@ //#region src/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue?vue&type=script&setup=true&lang.ts

class: "group/item flex w-full items-center gap-1.5",
onClick: _cache[0] || (_cache[0] = withModifiers(($event) => handleSelectEnvironment(""), ["stop"]))
onClick: _cache[0] || (_cache[0] = ($event) => handleSelectEnvironment(""))
}, {

@@ -77,3 +77,3 @@ default: withCtx(() => [createElementVNode("div", { class: normalizeClass(["flex h-4 w-4 items-center justify-center rounded-full p-[3px]", !__props.activeEnvironment ? "bg-c-accent text-b-1" : "shadow-border text-transparent"]) }, [createVNode(unref(ScalarIcon), {

class: "group/item flex w-full min-w-0 items-center gap-1.5 overflow-hidden text-ellipsis whitespace-nowrap",
onClick: withModifiers(($event) => handleSelectEnvironment(environmentName), ["stop"])
onClick: ($event) => handleSelectEnvironment(environmentName)
}, {

@@ -80,0 +80,0 @@ default: withCtx(() => [createElementVNode("div", { class: normalizeClass(["flex h-4 w-4 items-center justify-center rounded-full p-[3px]", __props.activeEnvironment === environmentName ? "bg-c-accent text-b-1" : "shadow-border text-transparent"]) }, [createVNode(unref(ScalarIcon), {

@@ -1,1 +0,1 @@

{"version":3,"file":"EnvironmentSelector.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarDropdown,\n ScalarDropdownDivider,\n ScalarDropdownItem,\n ScalarIcon,\n} from '@scalar/components'\nimport { computed } from 'vue'\n\nconst { environments = [], activeEnvironment } = defineProps<{\n /** List of available environments */\n environments?: string[]\n /** Currently selected environment */\n activeEnvironment?: string\n}>()\n\nconst emit = defineEmits<{\n /** Emitted when an environment is selected */\n (e: 'select:environment', environmentName: string): void\n /** Emitted when user wants to add a new environment */\n (e: 'add:environment'): void\n}>()\n\n/** Whether an environment is currently active */\nconst hasActiveEnvironment = computed(() => !!activeEnvironment)\n\n/** Whether environments exist */\nconst hasEnvironments = computed(() => environments.length > 0)\n\n/** Whether the currently selected environment exists in the dropdown options */\nconst hasSelectedEnvironmentInOptions = computed(() => {\n if (!activeEnvironment) {\n return false\n }\n\n return environments.includes(activeEnvironment)\n})\n\n/** True when an environment is selected but unavailable in the current context */\nconst hasMissingActiveEnvironment = computed(\n () => hasActiveEnvironment.value && !hasSelectedEnvironmentInOptions.value,\n)\n\n/** Display text for the button */\nconst displayText = computed(() => {\n if (hasMissingActiveEnvironment.value) {\n return `${activeEnvironment} (Unavailable)`\n }\n\n if (hasActiveEnvironment.value) {\n return activeEnvironment\n }\n if (!hasEnvironments.value) {\n return 'Add Environment'\n }\n return 'Select Environment'\n})\n\n/** Button styling based on state */\nconst buttonClass = computed(() => {\n if (hasMissingActiveEnvironment.value) {\n return 'hover:bg-b-2 text-c-2 border-transparent'\n }\n\n if (hasActiveEnvironment.value) {\n return 'bg-c-accent/10 text-c-accent hover:bg-c-accent/20 border-c-accent/30'\n }\n if (!hasEnvironments.value) {\n return 'hover:bg-b-2 text-c-3 border-transparent'\n }\n return 'hover:bg-b-2 text-c-2 border-transparent'\n})\n\nconst handleAddEnvironment = () => {\n emit('add:environment')\n}\n\nconst handleSelectEnvironment = (environmentName: string) => {\n emit('select:environment', environmentName)\n}\n</script>\n\n<template>\n <div class=\"relative flex items-center\">\n <!-- Environment indicator badge (only show when active) -->\n\n <ScalarDropdown>\n <ScalarButton\n :aria-label=\"`Current environment: ${displayText}`\"\n class=\"line-clamp-1 h-full w-fit justify-start border px-2 py-1 font-normal transition-colors\"\n :class=\"buttonClass\"\n size=\"sm\"\n variant=\"ghost\">\n <div class=\"flex max-w-[220px] min-w-0 items-center gap-1.5\">\n <!-- Icon indicator -->\n <ScalarIcon\n class=\"shrink-0\"\n :class=\"\n hasActiveEnvironment && !hasMissingActiveEnvironment\n ? 'text-c-accent'\n : 'text-c-3'\n \"\n icon=\"Globe\"\n size=\"sm\" />\n\n <!-- Environment name -->\n <span\n class=\"text-xxs block max-w-[160px] min-w-0 truncate text-left font-medium\">\n {{ displayText }}\n </span>\n\n <!-- Dropdown arrow -->\n <ScalarIcon\n class=\"shrink-0\"\n icon=\"ChevronDown\"\n size=\"xs\" />\n </div>\n </ScalarButton>\n\n <template #items>\n <!-- No environment option (clear selection) -->\n <ScalarDropdownItem\n v-if=\"hasActiveEnvironment\"\n class=\"group/item flex w-full items-center gap-1.5\"\n @click.stop=\"handleSelectEnvironment('')\">\n <div\n class=\"flex h-4 w-4 items-center justify-center rounded-full p-[3px]\"\n :class=\"\n !activeEnvironment\n ? 'bg-c-accent text-b-1'\n : 'shadow-border text-transparent'\n \">\n <ScalarIcon\n class=\"size-2.5\"\n icon=\"Checkmark\"\n thickness=\"3\" />\n </div>\n <span class=\"text-c-2\">No Environment</span>\n </ScalarDropdownItem>\n\n <ScalarDropdownDivider v-if=\"hasActiveEnvironment && hasEnvironments\" />\n\n <!-- Environment list -->\n <ScalarDropdownItem\n v-for=\"environmentName in environments\"\n :key=\"environmentName\"\n class=\"group/item flex w-full min-w-0 items-center gap-1.5 overflow-hidden text-ellipsis whitespace-nowrap\"\n @click.stop=\"handleSelectEnvironment(environmentName)\">\n <div\n class=\"flex h-4 w-4 items-center justify-center rounded-full p-[3px]\"\n :class=\"\n activeEnvironment === environmentName\n ? 'bg-c-accent text-b-1'\n : 'shadow-border text-transparent'\n \">\n <ScalarIcon\n class=\"size-2.5\"\n icon=\"Checkmark\"\n thickness=\"3\" />\n </div>\n <span class=\"min-w-0 flex-1 truncate\">{{ environmentName }}</span>\n </ScalarDropdownItem>\n <ScalarDropdownDivider v-if=\"hasMissingActiveEnvironment\" />\n\n <ScalarDropdownItem\n v-if=\"hasMissingActiveEnvironment\"\n class=\"group/item flex h-auto w-full min-w-0 items-start gap-1.5 overflow-hidden\"\n disabled>\n <div\n class=\"bg-c-accent text-b-1 mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full p-[3px]\">\n <ScalarIcon\n class=\"size-2.5\"\n icon=\"Checkmark\"\n thickness=\"3\" />\n </div>\n <div class=\"min-w-0 flex-1 text-left\">\n <span class=\"block truncate\">\n {{ activeEnvironment }}\n </span>\n <span class=\"text-c-3 block truncate text-xs\">\n Not available in this context\n </span>\n </div>\n </ScalarDropdownItem>\n\n <ScalarDropdownDivider v-if=\"hasEnvironments\" />\n\n <!-- Add new environment button -->\n <ScalarDropdownItem\n class=\"text-c-accent flex items-center gap-1.5\"\n @click=\"handleAddEnvironment\">\n <div class=\"flex h-4 w-4 items-center justify-center\">\n <ScalarIcon\n icon=\"Add\"\n size=\"sm\" />\n </div>\n <span>{{\n hasEnvironments ? 'New Environment' : 'Create Environment'\n }}</span>\n </ScalarDropdownItem>\n\n <!-- Helper text for empty state -->\n <div\n v-if=\"!hasEnvironments && !hasActiveEnvironment\"\n class=\"text-c-3 px-2 py-1.5 text-xs\">\n <p class=\"mb-1\">\n Environments let you manage variables like API keys and base URLs\n across different contexts.\n </p>\n </div>\n </template>\n </ScalarDropdown>\n </div>\n</template>\n"],"mappings":"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"}
{"version":3,"file":"EnvironmentSelector.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarDropdown,\n ScalarDropdownDivider,\n ScalarDropdownItem,\n ScalarIcon,\n} from '@scalar/components'\nimport { computed } from 'vue'\n\nconst { environments = [], activeEnvironment } = defineProps<{\n /** List of available environments */\n environments?: string[]\n /** Currently selected environment */\n activeEnvironment?: string\n}>()\n\nconst emit = defineEmits<{\n /** Emitted when an environment is selected */\n (e: 'select:environment', environmentName: string): void\n /** Emitted when user wants to add a new environment */\n (e: 'add:environment'): void\n}>()\n\n/** Whether an environment is currently active */\nconst hasActiveEnvironment = computed(() => !!activeEnvironment)\n\n/** Whether environments exist */\nconst hasEnvironments = computed(() => environments.length > 0)\n\n/** Whether the currently selected environment exists in the dropdown options */\nconst hasSelectedEnvironmentInOptions = computed(() => {\n if (!activeEnvironment) {\n return false\n }\n\n return environments.includes(activeEnvironment)\n})\n\n/** True when an environment is selected but unavailable in the current context */\nconst hasMissingActiveEnvironment = computed(\n () => hasActiveEnvironment.value && !hasSelectedEnvironmentInOptions.value,\n)\n\n/** Display text for the button */\nconst displayText = computed(() => {\n if (hasMissingActiveEnvironment.value) {\n return `${activeEnvironment} (Unavailable)`\n }\n\n if (hasActiveEnvironment.value) {\n return activeEnvironment\n }\n if (!hasEnvironments.value) {\n return 'Add Environment'\n }\n return 'Select Environment'\n})\n\n/** Button styling based on state */\nconst buttonClass = computed(() => {\n if (hasMissingActiveEnvironment.value) {\n return 'hover:bg-b-2 text-c-2 border-transparent'\n }\n\n if (hasActiveEnvironment.value) {\n return 'bg-c-accent/10 text-c-accent hover:bg-c-accent/20 border-c-accent/30'\n }\n if (!hasEnvironments.value) {\n return 'hover:bg-b-2 text-c-3 border-transparent'\n }\n return 'hover:bg-b-2 text-c-2 border-transparent'\n})\n\nconst handleAddEnvironment = () => {\n emit('add:environment')\n}\n\nconst handleSelectEnvironment = (environmentName: string) => {\n emit('select:environment', environmentName)\n}\n</script>\n\n<template>\n <div class=\"relative flex items-center\">\n <!-- Environment indicator badge (only show when active) -->\n\n <ScalarDropdown>\n <ScalarButton\n :aria-label=\"`Current environment: ${displayText}`\"\n class=\"line-clamp-1 h-full w-fit justify-start border px-2 py-1 font-normal transition-colors\"\n :class=\"buttonClass\"\n size=\"sm\"\n variant=\"ghost\">\n <div class=\"flex max-w-[220px] min-w-0 items-center gap-1.5\">\n <!-- Icon indicator -->\n <ScalarIcon\n class=\"shrink-0\"\n :class=\"\n hasActiveEnvironment && !hasMissingActiveEnvironment\n ? 'text-c-accent'\n : 'text-c-3'\n \"\n icon=\"Globe\"\n size=\"sm\" />\n\n <!-- Environment name -->\n <span\n class=\"text-xxs block max-w-[160px] min-w-0 truncate text-left font-medium\">\n {{ displayText }}\n </span>\n\n <!-- Dropdown arrow -->\n <ScalarIcon\n class=\"shrink-0\"\n icon=\"ChevronDown\"\n size=\"xs\" />\n </div>\n </ScalarButton>\n\n <template #items>\n <!-- No environment option (clear selection) -->\n <ScalarDropdownItem\n v-if=\"hasActiveEnvironment\"\n class=\"group/item flex w-full items-center gap-1.5\"\n @click=\"handleSelectEnvironment('')\">\n <div\n class=\"flex h-4 w-4 items-center justify-center rounded-full p-[3px]\"\n :class=\"\n !activeEnvironment\n ? 'bg-c-accent text-b-1'\n : 'shadow-border text-transparent'\n \">\n <ScalarIcon\n class=\"size-2.5\"\n icon=\"Checkmark\"\n thickness=\"3\" />\n </div>\n <span class=\"text-c-2\">No Environment</span>\n </ScalarDropdownItem>\n\n <ScalarDropdownDivider v-if=\"hasActiveEnvironment && hasEnvironments\" />\n\n <!-- Environment list -->\n <ScalarDropdownItem\n v-for=\"environmentName in environments\"\n :key=\"environmentName\"\n class=\"group/item flex w-full min-w-0 items-center gap-1.5 overflow-hidden text-ellipsis whitespace-nowrap\"\n @click=\"handleSelectEnvironment(environmentName)\">\n <div\n class=\"flex h-4 w-4 items-center justify-center rounded-full p-[3px]\"\n :class=\"\n activeEnvironment === environmentName\n ? 'bg-c-accent text-b-1'\n : 'shadow-border text-transparent'\n \">\n <ScalarIcon\n class=\"size-2.5\"\n icon=\"Checkmark\"\n thickness=\"3\" />\n </div>\n <span class=\"min-w-0 flex-1 truncate\">{{ environmentName }}</span>\n </ScalarDropdownItem>\n <ScalarDropdownDivider v-if=\"hasMissingActiveEnvironment\" />\n\n <ScalarDropdownItem\n v-if=\"hasMissingActiveEnvironment\"\n class=\"group/item flex h-auto w-full min-w-0 items-start gap-1.5 overflow-hidden\"\n disabled>\n <div\n class=\"bg-c-accent text-b-1 mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full p-[3px]\">\n <ScalarIcon\n class=\"size-2.5\"\n icon=\"Checkmark\"\n thickness=\"3\" />\n </div>\n <div class=\"min-w-0 flex-1 text-left\">\n <span class=\"block truncate\">\n {{ activeEnvironment }}\n </span>\n <span class=\"text-c-3 block truncate text-xs\">\n Not available in this context\n </span>\n </div>\n </ScalarDropdownItem>\n\n <ScalarDropdownDivider v-if=\"hasEnvironments\" />\n\n <!-- Add new environment button -->\n <ScalarDropdownItem\n class=\"text-c-accent flex items-center gap-1.5\"\n @click=\"handleAddEnvironment\">\n <div class=\"flex h-4 w-4 items-center justify-center\">\n <ScalarIcon\n icon=\"Add\"\n size=\"sm\" />\n </div>\n <span>{{\n hasEnvironments ? 'New Environment' : 'Create Environment'\n }}</span>\n </ScalarDropdownItem>\n\n <!-- Helper text for empty state -->\n <div\n v-if=\"!hasEnvironments && !hasActiveEnvironment\"\n class=\"text-c-3 px-2 py-1.5 text-xs\">\n <p class=\"mb-1\">\n Environments let you manage variables like API keys and base URLs\n across different contexts.\n </p>\n </div>\n </template>\n </ScalarDropdown>\n </div>\n</template>\n"],"mappings":"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"}

@@ -1,1 +0,1 @@

{"version":3,"file":"AuthSelector.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarComboboxMultiselect,\n ScalarIconButton,\n ScalarListboxCheckbox,\n useModal,\n type Icon,\n type ScalarButton as ScalarButtonType,\n} from '@scalar/components'\nimport { ScalarIconCaretDown, ScalarIconTrash } from '@scalar/icons'\nimport type { SelectedSecurity } from '@scalar/workspace-store/entities/auth'\nimport type {\n AuthMeta,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport {\n isAuthOptional,\n type MergedSecuritySchemes,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type {\n OpenApiDocument,\n SecurityRequirementObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, ref, useId } from 'vue'\n\nimport DeleteRequestAuthModal from '@/v2/blocks/scalar-auth-selector-block/components/DeleteRequestAuthModal.vue'\nimport type { OAuth2Options } from '@/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue'\nimport {\n formatComplexScheme,\n formatScheme,\n getSecuritySchemeOptions,\n type SecuritySchemeOption,\n} from '@/v2/blocks/scalar-auth-selector-block/helpers/security-scheme'\nimport { CollapsibleSection } from '@/v2/components/layout'\n\nimport RequestAuthDataTable from './RequestAuthDataTable.vue'\n\nconst {\n environment,\n eventBus,\n createAnySecurityScheme = false,\n defaultOpen = true,\n isStatic = false,\n meta,\n proxyUrl,\n securityRequirements,\n securitySchemes,\n selectedSecurity,\n server,\n title,\n options,\n} = defineProps<{\n environment: XScalarEnvironment\n eventBus: WorkspaceEventBus\n /** Allows adding authentication which is not in the document */\n createAnySecurityScheme?: boolean\n /** Whether the authentication disclosure should start expanded */\n defaultOpen?: boolean\n /** Creates a static disclosure that cannot be collapsed */\n isStatic?: boolean\n meta: AuthMeta\n proxyUrl: string\n securityRequirements: OpenApiDocument['security']\n securitySchemes: MergedSecuritySchemes\n selectedSecurity: SelectedSecurity | undefined\n server: ServerObject | null\n title: string\n /** Any config options required for the OAuth2 flow */\n options?: OAuth2Options\n}>()\n\nconst titleId = useId()\nconst comboboxButtonRef = ref<typeof ScalarButtonType | null>(null)\nconst isDisclosureOpen = ref(false)\n\nconst deleteModal = useModal()\nconst schemeToDelete = ref<{\n label: string\n payload: SecurityRequirementObject\n} | null>(null)\n\n/**\n * Determines if authentication is required or optional\n *\n * Auth is optional when there is an empty security requirement and no complex requirements.\n * Complex requirements have multiple auth schemes combined (e.g., API key + OAuth).\n */\nconst authIndicator = computed<{ icon: Icon; text: string } | null>(() => {\n if (!securityRequirements?.length) {\n return null\n }\n\n const isOptional = isAuthOptional(securityRequirements)\n\n return {\n icon: isOptional ? 'Unlock' : 'Lock',\n text: isOptional ? 'Optional' : 'Required',\n }\n})\n\n/** All available auth scheme options for the dropdown */\nconst availableSchemeOptions = computed(() =>\n getSecuritySchemeOptions(\n securityRequirements ?? [],\n securitySchemes ?? {},\n selectedSecurity?.selectedSchemes ?? [],\n createAnySecurityScheme,\n ),\n)\n\n/** Currently active auth schemes selected for this operation or collection */\nconst activeSchemeOptions = computed<SecuritySchemeOption[]>(() => {\n const schemes = selectedSecurity?.selectedSchemes\n if (!schemes?.length) {\n return []\n }\n\n return schemes.flatMap((requirement) => {\n const schemeNames = Object.keys(requirement)\n\n if (schemeNames.length === 0) {\n return []\n }\n\n // Complex auth requirement with multiple schemes\n if (schemeNames.length > 1) {\n return formatComplexScheme(requirement)\n }\n\n // Simple auth requirement with single scheme\n const schemeName = schemeNames[0]\n if (!schemeName) {\n return []\n }\n\n const scheme = getResolvedRef(securitySchemes?.[schemeName])\n if (!scheme) {\n return []\n }\n\n return formatScheme({\n name: schemeName,\n value: requirement,\n })\n })\n})\n\n/**\n * Opens the combobox dropdown when clicking the auth indicator badge.\n * Prevents the disclosure from toggling if it is already open.\n */\nconst handleAuthIndicatorClick = (event: Event): void => {\n if (isDisclosureOpen.value) {\n event.stopPropagation()\n }\n comboboxButtonRef.value?.$el.click()\n}\n\n/**\n * Updates the selected auth schemes.\n * Separates existing schemes from newly created ones for the event payload.\n */\nconst handleSchemeSelection = (selected: SecuritySchemeOption[]): void => {\n const existingSchemes = selected\n .filter((option) => option.payload === undefined)\n .map((option) => unpackProxyObject(option.value, { depth: 2 }))\n\n const newSchemes = selected\n .filter((option) => option.payload !== undefined)\n .map((option) => ({\n name: option.label,\n scheme: option.payload!,\n }))\n\n eventBus.emit('auth:update:selected-security-schemes', {\n selectedRequirements: existingSchemes,\n newSchemes,\n meta,\n })\n}\n\n/** Shows the delete confirmation modal for the selected scheme */\nconst handleDeleteRequest = (option: {\n label: string\n value: SecurityRequirementObject\n}): void => {\n schemeToDelete.value = { label: option.label, payload: option.value }\n deleteModal.show()\n}\n\n/** Deletes the selected auth scheme after confirmation */\nconst handleDeleteConfirm = (): void => {\n if (!schemeToDelete.value) {\n return\n }\n\n eventBus.emit('auth:delete:security-scheme', {\n names: Object.keys(schemeToDelete.value.payload),\n })\n\n schemeToDelete.value = null\n deleteModal.hide()\n}\n\ndefineExpose({\n authIndicator,\n selectedSchemeOptions: activeSchemeOptions,\n schemeOptions: availableSchemeOptions,\n})\n</script>\n<template>\n <CollapsibleSection\n class=\"group/params relative\"\n :defaultOpen\n :isStatic=\"isStatic\"\n :itemCount=\"activeSchemeOptions.length\"\n @update:modelValue=\"(open) => (isDisclosureOpen = open)\">\n <template #title>\n <div\n :id=\"titleId\"\n class=\"inline-flex items-center gap-0.5 leading-[20px]\">\n <span>{{ title }}</span>\n\n <span\n v-if=\"authIndicator\"\n class=\"text-c-3 hover:bg-b-3 hover:text-c-1 -my-0.5 -mr-1 cursor-pointer rounded px-1 py-0.5 leading-[normal] font-normal\"\n :class=\"{ 'text-c-1': authIndicator.text === 'Required' }\"\n data-testid=\"auth-indicator\"\n @click=\"handleAuthIndicatorClick\">\n {{ authIndicator.text }}\n </span>\n </div>\n </template>\n\n <!-- Auth Dropdown (hidden when only one scheme is available) -->\n <template #actions>\n <ScalarComboboxMultiselect\n class=\"w-72 text-xs\"\n :modelValue=\"activeSchemeOptions\"\n multiple\n :options=\"availableSchemeOptions\"\n placement=\"bottom-end\"\n teleport\n @delete=\"handleDeleteRequest\"\n @update:modelValue=\"handleSchemeSelection\">\n <ScalarButton\n ref=\"comboboxButtonRef\"\n :aria-describedby=\"titleId\"\n class=\"group/combobox-button hover:text-c-1 text-c-2 flex h-fit w-full items-center gap-1 px-0.75 py-0.25 text-base font-normal\"\n variant=\"ghost\">\n <!-- Single auth scheme selected -->\n <template v-if=\"activeSchemeOptions.length === 1\">\n <span class=\"sr-only\">Selected Auth Type:</span>\n {{ activeSchemeOptions[0]?.label }}\n </template>\n\n <!-- Multiple auth schemes selected -->\n <template v-else-if=\"activeSchemeOptions.length > 1\">\n Multiple\n <span class=\"sr-only\">Auth Types Selected</span>\n </template>\n\n <!-- No auth schemes selected -->\n <template v-else>\n <span class=\"sr-only\">Select</span>\n Auth Type\n </template>\n\n <ScalarIconCaretDown\n class=\"size-3 shrink-0 transition-transform duration-100 group-aria-expanded/combobox-button:rotate-180\"\n weight=\"bold\" />\n </ScalarButton>\n\n <template #option=\"{ option, selected }\">\n <ScalarListboxCheckbox\n multiselect\n :selected=\"selected\" />\n <div class=\"min-w-0 flex-1 truncate\">\n {{ option.label }}\n </div>\n <ScalarIconButton\n v-if=\"option.isDeletable\"\n class=\"-m-0.5 shrink-0 p-0.5 opacity-0 group-hover/item:opacity-100\"\n :icon=\"ScalarIconTrash\"\n :label=\"`Delete ${option.label}`\"\n size=\"xs\"\n @click.stop=\"handleDeleteRequest(option)\" />\n </template>\n </ScalarComboboxMultiselect>\n </template>\n\n <!-- Auth Table -->\n <RequestAuthDataTable\n :activeAuthIndex=\"selectedSecurity?.selectedIndex ?? 0\"\n :environment\n :eventBus\n :isStatic\n :meta\n :options\n :proxyUrl\n :securitySchemes\n :selectedSchemeOptions=\"activeSchemeOptions\"\n :server />\n\n <!-- Delete Auth Modal -->\n <DeleteRequestAuthModal\n v-if=\"schemeToDelete\"\n :label=\"schemeToDelete.label\"\n :scheme=\"schemeToDelete\"\n :state=\"deleteModal\"\n @close=\"deleteModal.hide()\"\n @delete=\"handleDeleteConfirm\" />\n </CollapsibleSection>\n</template>\n"],"mappings":"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"}
{"version":3,"file":"AuthSelector.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarComboboxMultiselect,\n ScalarIconButton,\n ScalarListboxCheckbox,\n useModal,\n type Icon,\n type ScalarButton as ScalarButtonType,\n} from '@scalar/components'\nimport { ScalarIconCaretDown, ScalarIconTrash } from '@scalar/icons'\nimport type { SelectedSecurity } from '@scalar/workspace-store/entities/auth'\nimport type {\n AuthMeta,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport {\n isAuthOptional,\n type MergedSecuritySchemes,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type {\n OpenApiDocument,\n SecurityRequirementObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, ref, useId } from 'vue'\n\nimport DeleteRequestAuthModal from '@/v2/blocks/scalar-auth-selector-block/components/DeleteRequestAuthModal.vue'\nimport type { OAuth2Options } from '@/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue'\nimport {\n formatComplexScheme,\n formatScheme,\n getSecuritySchemeOptions,\n type SecuritySchemeOption,\n} from '@/v2/blocks/scalar-auth-selector-block/helpers/security-scheme'\nimport { CollapsibleSection } from '@/v2/components/layout'\n\nimport RequestAuthDataTable from './RequestAuthDataTable.vue'\n\nconst {\n environment,\n eventBus,\n createAnySecurityScheme = false,\n defaultOpen = true,\n isStatic = false,\n meta,\n proxyUrl,\n securityRequirements,\n securitySchemes,\n selectedSecurity,\n server,\n title,\n options,\n} = defineProps<{\n environment: XScalarEnvironment\n eventBus: WorkspaceEventBus\n /** Allows adding authentication which is not in the document */\n createAnySecurityScheme?: boolean\n /** Whether the authentication disclosure should start expanded */\n defaultOpen?: boolean\n /** Creates a static disclosure that cannot be collapsed */\n isStatic?: boolean\n meta: AuthMeta\n proxyUrl: string\n securityRequirements: OpenApiDocument['security']\n securitySchemes: MergedSecuritySchemes\n selectedSecurity: SelectedSecurity | undefined\n server: ServerObject | null\n title: string\n /** Any config options required for the OAuth2 flow */\n options?: OAuth2Options\n}>()\n\nconst titleId = useId()\nconst comboboxButtonRef = ref<typeof ScalarButtonType | null>(null)\nconst isDisclosureOpen = ref(false)\n\nconst deleteModal = useModal()\nconst schemeToDelete = ref<{\n label: string\n payload: SecurityRequirementObject\n} | null>(null)\n\n/**\n * Determines if authentication is required or optional\n *\n * Auth is optional when there is an empty security requirement and no complex requirements.\n * Complex requirements have multiple auth schemes combined (e.g., API key + OAuth).\n */\nconst authIndicator = computed<{ icon: Icon; text: string } | null>(() => {\n if (!securityRequirements?.length) {\n return null\n }\n\n const isOptional = isAuthOptional(securityRequirements)\n\n return {\n icon: isOptional ? 'Unlock' : 'Lock',\n text: isOptional ? 'Optional' : 'Required',\n }\n})\n\n/** All available auth scheme options for the dropdown */\nconst availableSchemeOptions = computed(() =>\n getSecuritySchemeOptions(\n securityRequirements ?? [],\n securitySchemes ?? {},\n selectedSecurity?.selectedSchemes ?? [],\n createAnySecurityScheme,\n ),\n)\n\n/** Currently active auth schemes selected for this operation or collection */\nconst activeSchemeOptions = computed<SecuritySchemeOption[]>(() => {\n const schemes = selectedSecurity?.selectedSchemes\n if (!schemes?.length) {\n return []\n }\n\n return schemes.flatMap((requirement) => {\n const schemeNames = Object.keys(requirement)\n\n if (schemeNames.length === 0) {\n return []\n }\n\n // Complex auth requirement with multiple schemes\n if (schemeNames.length > 1) {\n return formatComplexScheme(requirement)\n }\n\n // Simple auth requirement with single scheme\n const schemeName = schemeNames[0]\n if (!schemeName) {\n return []\n }\n\n const scheme = getResolvedRef(securitySchemes?.[schemeName])\n if (!scheme) {\n return []\n }\n\n return formatScheme({\n name: schemeName,\n value: requirement,\n })\n })\n})\n\n/**\n * Opens the combobox dropdown when clicking the auth indicator badge.\n * Prevents the disclosure from toggling if it is already open.\n */\nconst handleAuthIndicatorClick = (event: Event): void => {\n if (isDisclosureOpen.value) {\n event.stopPropagation()\n }\n comboboxButtonRef.value?.$el.click()\n}\n\n/**\n * Updates the selected auth schemes.\n * Separates existing schemes from newly created ones for the event payload.\n */\nconst handleSchemeSelection = (selected: SecuritySchemeOption[]): void => {\n const existingSchemes = selected\n .filter((option) => option.payload === undefined)\n .map((option) => unpackProxyObject(option.value, { depth: 2 }))\n\n const newSchemes = selected\n .filter((option) => option.payload !== undefined)\n .map((option) => ({\n name: option.label,\n scheme: option.payload!,\n }))\n\n eventBus.emit('auth:update:selected-security-schemes', {\n selectedRequirements: existingSchemes,\n newSchemes,\n meta,\n })\n}\n\n/** Shows the delete confirmation modal for the selected scheme */\nconst handleDeleteRequest = (option: {\n label: string\n value: SecurityRequirementObject\n}): void => {\n schemeToDelete.value = { label: option.label, payload: option.value }\n deleteModal.show()\n}\n\n/** Deletes the selected auth scheme after confirmation */\nconst handleDeleteConfirm = (): void => {\n if (!schemeToDelete.value) {\n return\n }\n\n eventBus.emit('auth:delete:security-scheme', {\n names: Object.keys(schemeToDelete.value.payload),\n })\n\n schemeToDelete.value = null\n deleteModal.hide()\n}\n\ndefineExpose({\n authIndicator,\n selectedSchemeOptions: activeSchemeOptions,\n schemeOptions: availableSchemeOptions,\n})\n</script>\n<template>\n <CollapsibleSection\n class=\"group/params relative\"\n :defaultOpen\n :isStatic=\"isStatic\"\n :itemCount=\"activeSchemeOptions.length\"\n @update:modelValue=\"(open) => (isDisclosureOpen = open)\">\n <template #title>\n <div\n :id=\"titleId\"\n class=\"inline-flex items-center gap-0.5 leading-[20px]\">\n <span>{{ title }}</span>\n\n <span\n v-if=\"authIndicator\"\n class=\"text-c-3 hover:bg-b-3 hover:text-c-1 -my-0.5 -mr-1 cursor-pointer rounded px-1 py-0.5 leading-[normal] font-normal\"\n :class=\"{ 'text-c-1': authIndicator.text === 'Required' }\"\n data-testid=\"auth-indicator\"\n @click=\"handleAuthIndicatorClick\">\n {{ authIndicator.text }}\n </span>\n </div>\n </template>\n\n <!-- Auth Dropdown (hidden when only one scheme is available) -->\n <template #actions>\n <ScalarComboboxMultiselect\n class=\"w-72 text-xs\"\n :modelValue=\"activeSchemeOptions\"\n multiple\n :options=\"availableSchemeOptions\"\n placement=\"bottom-end\"\n teleport\n @delete=\"handleDeleteRequest\"\n @update:modelValue=\"handleSchemeSelection\">\n <ScalarButton\n ref=\"comboboxButtonRef\"\n :aria-describedby=\"titleId\"\n class=\"group/combobox-button hover:text-c-1 text-c-2 flex h-fit w-full items-center gap-1 px-0.75 py-0.25 text-base font-normal\"\n variant=\"ghost\">\n <!-- Single auth scheme selected -->\n <template v-if=\"activeSchemeOptions.length === 1\">\n <span class=\"sr-only\">Selected Auth Type:</span>\n {{ activeSchemeOptions[0]?.label }}\n </template>\n\n <!-- Multiple auth schemes selected -->\n <template v-else-if=\"activeSchemeOptions.length > 1\">\n Multiple\n <span class=\"sr-only\">Auth Types Selected</span>\n </template>\n\n <!-- No auth schemes selected -->\n <template v-else>\n <span class=\"sr-only\">Select</span>\n Auth Type\n </template>\n\n <ScalarIconCaretDown\n class=\"size-3 shrink-0 transition-transform duration-100 group-aria-expanded/combobox-button:rotate-180\"\n weight=\"bold\" />\n </ScalarButton>\n\n <template #option=\"{ option, selected }\">\n <ScalarListboxCheckbox\n multiselect\n :selected=\"selected\" />\n <div class=\"min-w-0 flex-1 truncate\">\n {{ option.label }}\n </div>\n <ScalarIconButton\n v-if=\"option.isDeletable\"\n class=\"-m-0.5 shrink-0 p-0.5 opacity-0 group-hover/item:opacity-100\"\n :icon=\"ScalarIconTrash\"\n :label=\"`Delete ${option.label}`\"\n size=\"xs\"\n @click.stop=\"handleDeleteRequest(option)\" />\n </template>\n </ScalarComboboxMultiselect>\n </template>\n\n <!-- Auth Table -->\n <RequestAuthDataTable\n :activeAuthIndex=\"selectedSecurity?.selectedIndex ?? 0\"\n :environment\n :eventBus\n :isStatic\n :meta\n :options\n :proxyUrl\n :securitySchemes\n :selectedSchemeOptions=\"activeSchemeOptions\"\n :server />\n\n <!-- Delete Auth Modal -->\n <DeleteRequestAuthModal\n v-if=\"schemeToDelete\"\n :label=\"schemeToDelete.label\"\n :scheme=\"schemeToDelete\"\n :state=\"deleteModal\"\n @close=\"deleteModal.hide()\"\n @delete=\"handleDeleteConfirm\" />\n </CollapsibleSection>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4EA,MAAM,UAAU,OAAM;EACtB,MAAM,oBAAoB,IAAoC,KAAI;EAClE,MAAM,mBAAmB,IAAI,MAAK;EAElC,MAAM,cAAc,UAAS;EAC7B,MAAM,iBAAiB,IAGb,KAAI;;;;;;;EAQd,MAAM,gBAAgB,eAAoD;AACxE,OAAI,CAAC,QAAA,sBAAsB,OACzB,QAAO;GAGT,MAAM,aAAa,eAAe,QAAA,qBAAoB;AAEtD,UAAO;IACL,MAAM,aAAa,WAAW;IAC9B,MAAM,aAAa,aAAa;IAClC;IACD;;EAGD,MAAM,yBAAyB,eAC7B,yBACE,QAAA,wBAAwB,EAAE,EAC1B,QAAA,mBAAmB,EAAE,EACrB,QAAA,kBAAkB,mBAAmB,EAAE,EACvC,QAAA,wBACD,CACH;;EAGA,MAAM,sBAAsB,eAAuC;GACjE,MAAM,UAAU,QAAA,kBAAkB;AAClC,OAAI,CAAC,SAAS,OACZ,QAAO,EAAC;AAGV,UAAO,QAAQ,SAAS,gBAAgB;IACtC,MAAM,cAAc,OAAO,KAAK,YAAW;AAE3C,QAAI,YAAY,WAAW,EACzB,QAAO,EAAC;AAIV,QAAI,YAAY,SAAS,EACvB,QAAO,oBAAoB,YAAW;IAIxC,MAAM,aAAa,YAAY;AAC/B,QAAI,CAAC,WACH,QAAO,EAAC;AAIV,QAAI,CADW,eAAe,QAAA,kBAAkB,YAAW,CAEzD,QAAO,EAAC;AAGV,WAAO,aAAa;KAClB,MAAM;KACN,OAAO;KACR,CAAA;KACF;IACF;;;;;EAMD,MAAM,4BAA4B,UAAuB;AACvD,OAAI,iBAAiB,MACnB,OAAM,iBAAgB;AAExB,qBAAkB,OAAO,IAAI,OAAM;;;;;;EAOrC,MAAM,yBAAyB,aAA2C;GACxE,MAAM,kBAAkB,SACrB,QAAQ,WAAW,OAAO,YAAY,KAAA,EAAS,CAC/C,KAAK,WAAW,kBAAkB,OAAO,OAAO,EAAE,OAAO,GAAG,CAAC,CAAA;GAEhE,MAAM,aAAa,SAChB,QAAQ,WAAW,OAAO,YAAY,KAAA,EAAS,CAC/C,KAAK,YAAY;IAChB,MAAM,OAAO;IACb,QAAQ,OAAO;IAChB,EAAC;AAEJ,WAAA,SAAS,KAAK,yCAAyC;IACrD,sBAAsB;IACtB;IACA,MAAG,QAAA;IACJ,CAAA;;;EAIH,MAAM,uBAAuB,WAGjB;AACV,kBAAe,QAAQ;IAAE,OAAO,OAAO;IAAO,SAAS,OAAO;IAAM;AACpE,eAAY,MAAK;;;EAInB,MAAM,4BAAkC;AACtC,OAAI,CAAC,eAAe,MAClB;AAGF,WAAA,SAAS,KAAK,+BAA+B,EAC3C,OAAO,OAAO,KAAK,eAAe,MAAM,QAAQ,EACjD,CAAA;AAED,kBAAe,QAAQ;AACvB,eAAY,MAAK;;AAGnB,WAAa;GACX;GACA,uBAAuB;GACvB,eAAe;GAChB,CAAA;;uBAGC,YAqGqB,MAAA,2BAAA,EAAA;IApGnB,OAAM;IACL,aAAA,QAAA;IACA,UAAU,QAAA;IACV,WAAW,oBAAA,MAAoB;IAC/B,uBAAiB,OAAA,OAAA,OAAA,MAAG,SAAU,iBAAA,QAAmB;;IACvC,OAAK,cAcR,CAbN,mBAaM,OAAA;KAZH,IAAI,MAAA,QAAO;KACZ,OAAM;QACN,mBAAwB,QAAA,MAAA,gBAAf,QAAA,MAAK,EAAA,EAAA,EAGN,cAAA,SAAA,WAAA,EADR,mBAOO,QAAA;;KALL,OAAK,eAAA,CAAC,sHAAoH,EAAA,YACpG,cAAA,MAAc,SAAI,YAAA,CAAA,CAAA;KACxC,eAAY;KACX,SAAO;uBACL,cAAA,MAAc,KAAI,EAAA,EAAA,IAAA,mBAAA,IAAA,KAAA,CAAA,EAAA,GAAA,WAAA,CAAA,CAAA;IAMhB,SAAO,cAqDY,CApD5B,YAoD4B,MAAA,0BAAA,EAAA;KAnD1B,OAAM;KACL,YAAY,oBAAA;KACb,UAAA;KACC,SAAS,uBAAA;KACV,WAAU;KACV,UAAA;KACC,UAAQ;KACR,uBAAmB;;KA6BT,QAAM,SAGU,EAHN,QAAQ,eAAQ;MACnC,YAEyB,MAAA,sBAAA,EAAA;OADvB,aAAA;OACW;;MACb,mBAEM,OAFN,YAEM,gBADD,OAAO,MAAK,EAAA,EAAA;MAGT,OAAO,eAAA,WAAA,EADf,YAM8C,MAAA,iBAAA,EAAA;;OAJ5C,OAAM;OACL,MAAM,MAAA,gBAAe;OACrB,OAAK,UAAY,OAAO;OACzB,MAAK;OACJ,SAAK,eAAA,WAAO,oBAAoB,OAAM,EAAA,CAAA,OAAA,CAAA;;;;;;;4BAf5B,CA1Bf,YA0Be,MAAA,aAAA,EAAA;eAzBT;MAAJ,KAAI;MACH,oBAAkB,MAAA,QAAO;MAC1B,OAAM;MACN,SAAQ;;6BAoBD,CAlBS,oBAAA,MAAoB,WAAM,KAAA,WAAA,EAA1C,mBAGW,UAAA,EAAA,KAAA,GAAA,EAAA,CAAA,OAAA,OAAA,OAAA,KAFT,mBAAgD,QAAA,EAA1C,OAAM,WAAS,EAAC,uBAAmB,GAAA,GAAA,gBAAO,MAChD,gBAAG,oBAAA,MAAmB,IAAK,MAAK,EAAA,EAAA,CAAA,EAAA,GAAA,IAIb,oBAAA,MAAoB,SAAM,KAAA,WAAA,EAA/C,mBAGW,UAAA,EAAA,KAAA,GAAA,EAAA,CAAA,OAAA,OAAA,OAAA,KAAA,gBAH0C,cAEnD,GAAA,GAAA,OAAA,OAAA,OAAA,KAAA,mBAAgD,QAAA,EAA1C,OAAM,WAAS,EAAC,uBAAmB,GAAA,EAAA,EAAA,GAAA,KAAA,WAAA,EAI3C,mBAGW,UAAA,EAAA,KAAA,GAAA,EAAA,CAAA,OAAA,OAAA,OAAA,KAFT,mBAAmC,QAAA,EAA7B,OAAM,WAAS,EAAC,UAAM,GAAA,GAAA,OAAA,OAAA,OAAA,KAAA,gBAAO,eAErC,GAAA,EAAA,EAAA,GAAA,GAEA,YAEkB,MAAA,oBAAA,EAAA;OADhB,OAAM;OACN,QAAO;;;;;;2BAgCH,CAVZ,YAUY,8BAAA;KATT,iBAAiB,QAAA,kBAAkB,iBAAa;KAChD,aAAA,QAAA;KACA,UAAA,QAAA;KACA,UAAA,QAAA;KACA,MAAA,QAAA;KACA,SAAA,QAAA;KACA,UAAA,QAAA;KACA,iBAAA,QAAA;KACA,uBAAuB,oBAAA;KACvB,QAAA,QAAA;;;;;;;;;;;;QAIK,eAAA,SAAA,WAAA,EADR,YAMkC,gCAAA;;KAJ/B,OAAO,eAAA,MAAe;KACtB,QAAQ,eAAA;KACR,OAAO,MAAA,YAAW;KAClB,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,MAAA,YAAW,CAAC,MAAI;KACvB,UAAQ"}

@@ -1,1 +0,1 @@

{"version":3,"file":"OAuth2.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue"],"names":[],"mappings":"AAyaA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AAIzE,OAAO,KAAK,EAEV,iBAAiB,EAClB,MAAM,gCAAgC,CAAA;AACvC,OAAO,EAKL,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,EAChC,MAAM,yCAAyC,CAAA;AAChD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2EAA2E,CAAA;AAGnH,OAAO,KAAK,EAEV,YAAY,EACb,MAAM,8DAA8D,CAAA;AAWrE,uDAAuD;AACvD,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,sBAAsB,EAAE,mBAAmB,CAAC,CAAA;wBACxD,OAAO,YAAY;AAAxC,wBAAyC;AACzC,QAAA,MAAM,YAAY;IAEhB,wCAAwC;iBAC3B,kBAAkB;IAC/B,kBAAkB;WACX,sBAAsB;IAC7B,6BAA6B;UACvB,MAAM,sBAAsB;IAClC,sBAAsB;oBACN,MAAM,EAAE;IACxB,sBAAsB;YACd,0BAA0B;IAClC,mCAAmC;YAC3B,YAAY,GAAG,IAAI;IAC3B,gBAAgB;cACN,MAAM;IAChB,kCAAkC;UAC5B,MAAM;IACZ,2CAA2C;cACjC,iBAAiB;IAC3B,uDAAuD;cAC7C,aAAa;;;;;;;;;;;;;;IAnBvB,wCAAwC;iBAC3B,kBAAkB;IAC/B,kBAAkB;WACX,sBAAsB;IAC7B,6BAA6B;UACvB,MAAM,sBAAsB;IAClC,sBAAsB;oBACN,MAAM,EAAE;IACxB,sBAAsB;YACd,0BAA0B;IAClC,mCAAmC;YAC3B,YAAY,GAAG,IAAI;IAC3B,gBAAgB;cACN,MAAM;IAChB,kCAAkC;UAC5B,MAAM;IACZ,2CAA2C;cACjC,iBAAiB;IAC3B,uDAAuD;cAC7C,aAAa;;;;;;;;;;;;;kFAmxBrB,CAAC"}
{"version":3,"file":"OAuth2.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue"],"names":[],"mappings":"AAqhBA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AAIzE,OAAO,KAAK,EAEV,iBAAiB,EAClB,MAAM,gCAAgC,CAAA;AACvC,OAAO,EAKL,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,EAChC,MAAM,yCAAyC,CAAA;AAChD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2EAA2E,CAAA;AAGnH,OAAO,KAAK,EAEV,YAAY,EACb,MAAM,8DAA8D,CAAA;AAcrE,uDAAuD;AACvD,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,sBAAsB,EAAE,mBAAmB,CAAC,CAAA;wBACxD,OAAO,YAAY;AAAxC,wBAAyC;AACzC,QAAA,MAAM,YAAY;IAEhB,wCAAwC;iBAC3B,kBAAkB;IAC/B,kBAAkB;WACX,sBAAsB;IAC7B,6BAA6B;UACvB,MAAM,sBAAsB;IAClC,sBAAsB;oBACN,MAAM,EAAE;IACxB,sBAAsB;YACd,0BAA0B;IAClC,mCAAmC;YAC3B,YAAY,GAAG,IAAI;IAC3B,gBAAgB;cACN,MAAM;IAChB,kCAAkC;UAC5B,MAAM;IACZ,2CAA2C;cACjC,iBAAiB;IAC3B,uDAAuD;cAC7C,aAAa;;;;;;;;;;;;;;IAnBvB,wCAAwC;iBAC3B,kBAAkB;IAC/B,kBAAkB;WACX,sBAAsB;IAC7B,6BAA6B;UACvB,MAAM,sBAAsB;IAClC,sBAAsB;oBACN,MAAM,EAAE;IACxB,sBAAsB;YACd,0BAA0B;IAClC,mCAAmC;YAC3B,YAAY,GAAG,IAAI;IAC3B,gBAAgB;cACN,MAAM;IAChB,kCAAkC;UAC5B,MAAM;IACZ,2CAA2C;cACjC,iBAAiB;IAC3B,uDAAuD;cAC7C,aAAa;;;;;;;;;;;;;kFAq7BrB,CAAC"}

@@ -1,1 +0,1 @@

{"version":3,"file":"OAuth2.vue.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue"],"sourcesContent":["<script lang=\"ts\">\n/** Any config options required for the OAuth2 flow */\nexport type OAuth2Options = Pick<ApiClientConfiguration, 'oauth2RedirectUri'>\n</script>\n\n<script setup lang=\"ts\">\nimport { ScalarButton, useLoadingState } from '@scalar/components'\nimport type { ApiClientConfiguration } from '@scalar/types/api-reference'\nimport { pkceOptions } from '@scalar/types/entities'\nimport { useToasts } from '@scalar/use-toasts'\nimport type { SecretsOAuthFlows } from '@scalar/workspace-store/entities/auth'\nimport type {\n ApiReferenceEvents,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport {\n getEnvironmentVariables,\n type OAuthFlowAuthorizationCodeSecret,\n type OAuthFlowClientCredentialsSecret,\n type OAuthFlowPasswordSecret,\n type OAuthFlowsObjectSecret,\n type SecuritySchemeObjectSecret,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { XScalarCredentialsLocation } from '@scalar/workspace-store/schemas/extensions/security/x-scalar-credentials-location'\nimport { type XusePkce } from '@scalar/workspace-store/schemas/extensions/security/x-use-pkce'\nimport type {\n OAuthFlow,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, ref, watch } from 'vue'\n\nimport OAuthScopesInput from '@/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue'\nimport { authorizeOauth2 } from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth'\nimport { resolveDefaultOAuth2RedirectUri } from '@/v2/blocks/scalar-auth-selector-block/helpers/resolve-default-oauth2-redirect-url'\nimport { DataTableRow } from '@/v2/components/data-table'\n\nimport RequestAuthDataTableInput from './RequestAuthDataTableInput.vue'\n\nconst {\n environment,\n flows,\n type,\n scheme,\n selectedScopes: selectedScopesProp,\n server,\n proxyUrl,\n eventBus,\n name,\n options = {},\n} = defineProps<{\n /** Current environment configuration */\n environment: XScalarEnvironment\n /** OAuth flows */\n flows: OAuthFlowsObjectSecret\n /** Type of the OAuth flow */\n type: keyof OAuthFlowsObjectSecret\n /** Selected scopes */\n selectedScopes: string[]\n /** Security scheme */\n scheme: SecuritySchemeObjectSecret\n /** Current server configuration */\n server: ServerObject | null\n /** Proxy URL */\n proxyUrl: string\n /** Name of the security scheme */\n name: string\n /** Event bus for authentication updates */\n eventBus: WorkspaceEventBus\n /** Any config options required for the OAuth2 flow */\n options?: OAuth2Options\n}>()\n\nconst emits = defineEmits<{\n (\n e: 'update:selectedScopes',\n payload: Pick<\n ApiReferenceEvents['auth:update:selected-scopes'],\n 'scopes' | 'newScopePayload'\n >,\n ): void\n}>()\n\nconst loader = useLoadingState()\nconst { toast } = useToasts()\n\n/** The current OAuth flow based on the selected type */\nconst flow = computed(() => flows[type]!)\ntype NonImplicitFlow =\n | OAuthFlowPasswordSecret\n | OAuthFlowClientCredentialsSecret\n | OAuthFlowAuthorizationCodeSecret\n\n/** We filter selected scopes to only include scopes that are in this flow*/\nconst selectedScopes = computed(() =>\n selectedScopesProp.filter((scope) => scope in (flow.value.scopes ?? {})),\n)\n\n/** Updates the security scheme base */\nconst handleOauth2Update = (\n payload: Partial<OAuthFlow & XScalarCredentialsLocation>,\n): void => {\n // OpenIdConnect uses the secrets update for all\n if (scheme.type === 'openIdConnect') {\n return handleOauth2SecretsUpdate(payload)\n }\n\n eventBus.emit('auth:update:security-scheme', {\n payload: {\n type: scheme.type,\n flows: {\n [type]: payload,\n },\n },\n name,\n })\n}\n\n/** Updates the flow secrets */\nconst handleOauth2SecretsUpdate = (\n payload: Omit<Partial<SecretsOAuthFlows[keyof SecretsOAuthFlows]>, 'type'>,\n): void =>\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: {\n type: scheme.type,\n [type]: payload,\n },\n name,\n })\n\n/** Clears the flow secrets */\nconst clearOauth2Secrets = (): void =>\n eventBus.emit('auth:clear:security-scheme-secrets', {\n name,\n })\n\n/** Track if we have set the redirect uri */\nconst hasPrefilledRedirectUri = ref(false)\n\n/** Default the redirect-uri to the current origin if we have access to window */\nwatch(\n () =>\n (flow.value as OAuthFlowAuthorizationCodeSecret)[\n 'x-scalar-secret-redirect-uri'\n ],\n (newRedirectUri) => {\n const defaultRedirectUri = resolveDefaultOAuth2RedirectUri(options)\n\n if (\n hasPrefilledRedirectUri.value ||\n newRedirectUri ||\n !defaultRedirectUri ||\n !('x-scalar-secret-redirect-uri' in flow.value)\n ) {\n return\n }\n hasPrefilledRedirectUri.value = true\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-redirect-uri': defaultRedirectUri,\n })\n },\n { immediate: true },\n)\n\n/**\n * Authorizes the user using the specified OAuth flow.\n * Opens the appropriate OAuth dialog and/or performs the token exchange.\n */\nconst handleAuthorize = async (): Promise<void> => {\n if (loader.isLoading) {\n return\n }\n\n loader.start()\n\n const [error, tokens] = await authorizeOauth2(\n flows,\n type,\n selectedScopes.value,\n server,\n proxyUrl,\n getEnvironmentVariables(environment),\n )\n\n await loader.clear()\n\n if (tokens?.accessToken) {\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-token': tokens.accessToken,\n ...(tokens.refreshToken\n ? { 'x-scalar-secret-refresh-token': tokens.refreshToken }\n : {}),\n })\n } else {\n console.error(error)\n toast(error?.message ?? 'Failed to authorize', 'error')\n }\n}\n\n/** Updates the secret location */\nconst handleSecretLocationUpdate = (value: string): void => {\n const credentialsLocation = value === 'body' ? 'body' : 'header'\n\n if (scheme.type !== 'openIdConnect') {\n handleOauth2Update({\n 'x-scalar-credentials-location': credentialsLocation,\n })\n }\n\n handleOauth2SecretsUpdate({\n 'x-scalar-credentials-location': credentialsLocation,\n })\n}\n</script>\n\n<template>\n <!-- Access Token Display: Shows when user is already authorized -->\n <template v-if=\"Boolean(flow['x-scalar-secret-token'])\">\n <DataTableRow>\n <RequestAuthDataTableInput\n class=\"border-r-transparent\"\n :environment\n :modelValue=\"flow['x-scalar-secret-token']\"\n placeholder=\"QUxMIFlPVVIgQkFTRSBBUkUgQkVMT05HIFRPIFVT\"\n type=\"password\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-token': v })\n \">\n Access Token\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow class=\"min-w-full\">\n <div class=\"flex h-8 items-center justify-end gap-2 border-t\">\n <ScalarButton\n class=\"mr-1 p-0 px-2 py-0.5\"\n :loader\n size=\"sm\"\n variant=\"outlined\"\n @click=\"\n () =>\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-token': '',\n 'x-scalar-secret-refresh-token': '',\n })\n \">\n Clear\n </ScalarButton>\n </div>\n </DataTableRow>\n </template>\n\n <!-- Authorization Form: Shows when user needs to authorize -->\n <template v-else>\n <DataTableRow>\n <RequestAuthDataTableInput\n v-if=\"'authorizationUrl' in flow\"\n containerClass=\"border-r-0\"\n :environment\n :modelValue=\"flow['x-scalar-secret-auth-url'] ?? ''\"\n placeholder=\"https://galaxy.scalar.com/authorize\"\n @update:modelValue=\"\n (v) => {\n handleOauth2SecretsUpdate({ 'x-scalar-secret-auth-url': v })\n handleOauth2Update({ authorizationUrl: v })\n }\n \">\n Auth URL\n </RequestAuthDataTableInput>\n\n <RequestAuthDataTableInput\n v-if=\"'tokenUrl' in flow\"\n :environment\n :modelValue=\"flow['x-scalar-secret-token-url'] ?? ''\"\n placeholder=\"https://galaxy.scalar.com/token\"\n @update:modelValue=\"\n (v) => {\n handleOauth2SecretsUpdate({ 'x-scalar-secret-token-url': v })\n handleOauth2Update({ tokenUrl: v })\n }\n \">\n Token URL\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"'x-scalar-secret-redirect-uri' in flow\">\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"flow['x-scalar-secret-redirect-uri']\"\n placeholder=\"https://galaxy.scalar.com/callback\"\n @update:modelValue=\"\n (v) => {\n handleOauth2SecretsUpdate({ 'x-scalar-secret-redirect-uri': v })\n }\n \">\n Redirect URL\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <template\n v-if=\"\n 'x-scalar-secret-username' in flow && 'x-scalar-secret-password' in flow\n \">\n <DataTableRow>\n <RequestAuthDataTableInput\n class=\"text-c-2\"\n :environment\n :modelValue=\"flow['x-scalar-secret-username']\"\n placeholder=\"janedoe\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-username': v })\n \">\n Username\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow>\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"flow['x-scalar-secret-password']\"\n placeholder=\"********\"\n type=\"password\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-password': v })\n \">\n Password\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n\n <DataTableRow>\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"flow['x-scalar-secret-client-id']\"\n placeholder=\"12345\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-client-id': v })\n \">\n Client ID\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"'x-scalar-secret-client-secret' in flow\">\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"flow['x-scalar-secret-client-secret']\"\n placeholder=\"XYZ123\"\n type=\"password\"\n @update:modelValue=\"\n (v) =>\n handleOauth2SecretsUpdate({ 'x-scalar-secret-client-secret': v })\n \">\n Client Secret\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"'x-usePkce' in flow\">\n <RequestAuthDataTableInput\n :enum=\"pkceOptions\"\n :environment\n :modelValue=\"flow['x-usePkce']\"\n readOnly\n @update:modelValue=\"\n (v) =>\n handleOauth2Update({\n 'x-usePkce': v as XusePkce['x-usePkce'],\n })\n \">\n Use PKCE\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <!-- Credentials Location -->\n <DataTableRow v-if=\"type !== 'implicit'\">\n <RequestAuthDataTableInput\n :enum=\"['header', 'body']\"\n :environment\n :modelValue=\"\n (flow as NonImplicitFlow)['x-scalar-credentials-location'] || 'header'\n \"\n placeholder=\"header\"\n readOnly\n @update:modelValue=\"(v) => handleSecretLocationUpdate(v)\">\n Credentials Location\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <!-- Scopes -->\n <DataTableRow>\n <OAuthScopesInput\n :flow\n :flowType=\"type\"\n :selectedScopes\n @update:selectedScopes=\"(v) => emits('update:selectedScopes', v)\" />\n </DataTableRow>\n\n <DataTableRow class=\"min-w-full\">\n <div class=\"flex h-8 w-full items-center justify-end border-t\">\n <!-- Allow clearing the oauth section and going back to discovery -->\n <ScalarButton\n v-if=\"scheme.type === 'openIdConnect'\"\n class=\"mr-1 p-0 px-2 py-0.5\"\n :loader\n size=\"sm\"\n variant=\"outlined\"\n @click=\"clearOauth2Secrets\">\n Clear\n </ScalarButton>\n\n <ScalarButton\n class=\"mr-0.75 p-0 px-2 py-0.5\"\n :loader\n size=\"sm\"\n variant=\"outlined\"\n @click=\"handleAuthorize\">\n Authorize\n </ScalarButton>\n </div>\n </DataTableRow>\n </template>\n</template>\n"],"mappings":""}
{"version":3,"file":"OAuth2.vue.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue"],"sourcesContent":["<script lang=\"ts\">\n/** Any config options required for the OAuth2 flow */\nexport type OAuth2Options = Pick<ApiClientConfiguration, 'oauth2RedirectUri'>\n</script>\n\n<script setup lang=\"ts\">\nimport { ScalarButton, useLoadingState } from '@scalar/components'\nimport type { ApiClientConfiguration } from '@scalar/types/api-reference'\nimport { pkceOptions } from '@scalar/types/entities'\nimport { useToasts } from '@scalar/use-toasts'\nimport type { SecretsOAuthFlows } from '@scalar/workspace-store/entities/auth'\nimport type {\n ApiReferenceEvents,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport {\n getEnvironmentVariables,\n type OAuthFlowAuthorizationCodeSecret,\n type OAuthFlowClientCredentialsSecret,\n type OAuthFlowPasswordSecret,\n type OAuthFlowsObjectSecret,\n type SecuritySchemeObjectSecret,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { XScalarCredentialsLocation } from '@scalar/workspace-store/schemas/extensions/security/x-scalar-credentials-location'\nimport { type XusePkce } from '@scalar/workspace-store/schemas/extensions/security/x-use-pkce'\nimport type {\n OAuthFlow,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, ref, watch } from 'vue'\n\nimport OAuthScopesInput from '@/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue'\nimport {\n authorizeOauth2,\n refreshOauth2Token,\n} from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth'\nimport { resolveDefaultOAuth2RedirectUri } from '@/v2/blocks/scalar-auth-selector-block/helpers/resolve-default-oauth2-redirect-url'\nimport { DataTableRow } from '@/v2/components/data-table'\n\nimport RequestAuthDataTableInput from './RequestAuthDataTableInput.vue'\n\nconst {\n environment,\n flows,\n type,\n scheme,\n selectedScopes: selectedScopesProp,\n server,\n proxyUrl,\n eventBus,\n name,\n options = {},\n} = defineProps<{\n /** Current environment configuration */\n environment: XScalarEnvironment\n /** OAuth flows */\n flows: OAuthFlowsObjectSecret\n /** Type of the OAuth flow */\n type: keyof OAuthFlowsObjectSecret\n /** Selected scopes */\n selectedScopes: string[]\n /** Security scheme */\n scheme: SecuritySchemeObjectSecret\n /** Current server configuration */\n server: ServerObject | null\n /** Proxy URL */\n proxyUrl: string\n /** Name of the security scheme */\n name: string\n /** Event bus for authentication updates */\n eventBus: WorkspaceEventBus\n /** Any config options required for the OAuth2 flow */\n options?: OAuth2Options\n}>()\n\nconst emits = defineEmits<{\n (\n e: 'update:selectedScopes',\n payload: Pick<\n ApiReferenceEvents['auth:update:selected-scopes'],\n 'scopes' | 'newScopePayload'\n >,\n ): void\n}>()\n\nconst loader = useLoadingState()\nconst { toast } = useToasts()\n\n/** The current OAuth flow based on the selected type */\nconst flow = computed(() => flows[type]!)\ntype NonImplicitFlow =\n | OAuthFlowPasswordSecret\n | OAuthFlowClientCredentialsSecret\n | OAuthFlowAuthorizationCodeSecret\n\n/** We filter selected scopes to only include scopes that are in this flow*/\nconst selectedScopes = computed(() =>\n selectedScopesProp.filter((scope) => scope in (flow.value.scopes ?? {})),\n)\n\n/** Updates the security scheme base */\nconst handleOauth2Update = (\n payload: Partial<OAuthFlow & XScalarCredentialsLocation>,\n): void => {\n // OpenIdConnect uses the secrets update for all\n if (scheme.type === 'openIdConnect') {\n return handleOauth2SecretsUpdate(payload)\n }\n\n eventBus.emit('auth:update:security-scheme', {\n payload: {\n type: scheme.type,\n flows: {\n [type]: payload,\n },\n },\n name,\n })\n}\n\n/** Updates the flow secrets */\nconst handleOauth2SecretsUpdate = (\n payload: Omit<Partial<SecretsOAuthFlows[keyof SecretsOAuthFlows]>, 'type'>,\n): void =>\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: {\n type: scheme.type,\n [type]: payload,\n },\n name,\n })\n\n/** Clears the flow secrets */\nconst clearOauth2Secrets = (): void => {\n if (loader.isLoading) {\n return\n }\n eventBus.emit('auth:clear:security-scheme-secrets', {\n name,\n })\n}\n\n/** Clears stored access and refresh tokens (authorized state) */\nconst handleClearAccessTokens = (): void => {\n if (loader.isLoading) {\n return\n }\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-token': '',\n 'x-scalar-secret-refresh-token': '',\n })\n}\n\n/** Track redirect URI prefill per flow instance to support document switching */\nconst prefilledFlowIdentity = ref<string | null>(null)\nconst hasHandledRedirectPrefill = ref(false)\n\nconst resolveFlowIdentity = (\n currentFlow: OAuthFlowsObjectSecret[keyof OAuthFlowsObjectSecret] | undefined,\n): string =>\n JSON.stringify({\n type,\n authorizationUrl:\n currentFlow && 'authorizationUrl' in currentFlow\n ? currentFlow.authorizationUrl\n : '',\n tokenUrl:\n currentFlow && 'tokenUrl' in currentFlow ? currentFlow.tokenUrl : '',\n refreshUrl: currentFlow?.refreshUrl ?? '',\n scopes: Object.keys(currentFlow?.scopes ?? {}),\n })\n\n/** Default the redirect-uri to the current origin if we have access to window */\nwatch(\n () => flow.value,\n (currentFlow) => {\n if (!currentFlow || !('x-scalar-secret-redirect-uri' in currentFlow)) {\n return\n }\n\n const flowIdentity = resolveFlowIdentity(currentFlow)\n if (prefilledFlowIdentity.value !== flowIdentity) {\n prefilledFlowIdentity.value = flowIdentity\n hasHandledRedirectPrefill.value = false\n }\n\n if (hasHandledRedirectPrefill.value) {\n return\n }\n\n const newRedirectUri = (currentFlow as OAuthFlowAuthorizationCodeSecret)[\n 'x-scalar-secret-redirect-uri'\n ]\n const defaultRedirectUri = resolveDefaultOAuth2RedirectUri(options)\n\n hasHandledRedirectPrefill.value = true\n\n if (newRedirectUri || !defaultRedirectUri) {\n return\n }\n\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-redirect-uri': defaultRedirectUri,\n })\n },\n { immediate: true },\n)\n\n/**\n * Authorizes the user using the specified OAuth flow.\n * Opens the appropriate OAuth dialog and/or performs the token exchange.\n */\nconst handleAuthorize = async (): Promise<void> => {\n if (loader.isLoading) {\n return\n }\n\n loader.start()\n\n const [error, tokens] = await authorizeOauth2(\n flows,\n type,\n selectedScopes.value,\n server,\n proxyUrl,\n getEnvironmentVariables(environment),\n )\n\n await loader.clear()\n\n if (tokens?.accessToken) {\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-token': tokens.accessToken,\n ...(tokens.refreshToken\n ? { 'x-scalar-secret-refresh-token': tokens.refreshToken }\n : {}),\n })\n } else {\n console.error(error)\n toast(error?.message ?? 'Failed to authorize', 'error')\n }\n}\n\n/** Whether the current flow supports refreshing the access token */\nconst supportsRefreshToken = computed(() => type !== 'implicit')\n\n/**\n * Refresh URL placeholder, shows tokenUrl as hint if refreshUrl is not specified.\n * This helps users understand that tokenUrl will be used as fallback.\n */\nconst refreshUrlPlaceholder = computed(() => {\n if ('tokenUrl' in flow.value && flow.value.tokenUrl) {\n return flow.value.tokenUrl\n }\n return 'https://galaxy.scalar.com/oauth/refresh'\n})\n\n/**\n * Uses the stored refresh token to obtain a new access token\n * via grant_type=refresh_token.\n */\nconst handleRefresh = async (): Promise<void> => {\n if (loader.isLoading || type === 'implicit') {\n return\n }\n\n loader.start()\n\n const [error, tokens] = await refreshOauth2Token(\n flows,\n type,\n proxyUrl,\n server,\n getEnvironmentVariables(environment),\n )\n\n await loader.clear()\n\n if (tokens?.accessToken) {\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-token': tokens.accessToken,\n ...(tokens.refreshToken\n ? { 'x-scalar-secret-refresh-token': tokens.refreshToken }\n : {}),\n })\n } else {\n console.error(error)\n toast(error?.message ?? 'Failed to refresh token', 'error')\n }\n}\n\n/** Updates the secret location */\nconst handleSecretLocationUpdate = (value: string): void => {\n const credentialsLocation = value === 'body' ? 'body' : 'header'\n\n if (scheme.type !== 'openIdConnect') {\n handleOauth2Update({\n 'x-scalar-credentials-location': credentialsLocation,\n })\n }\n\n handleOauth2SecretsUpdate({\n 'x-scalar-credentials-location': credentialsLocation,\n })\n}\n</script>\n\n<template>\n <!-- Access Token Display: Shows when user is already authorized -->\n <template v-if=\"Boolean(flow['x-scalar-secret-token'])\">\n <DataTableRow>\n <RequestAuthDataTableInput\n class=\"border-r-transparent\"\n :environment\n :modelValue=\"flow['x-scalar-secret-token']\"\n placeholder=\"QUxMIFlPVVIgQkFTRSBBUkUgQkVMT05HIFRPIFVT\"\n type=\"password\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-token': v })\n \">\n Access Token\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"supportsRefreshToken\">\n <RequestAuthDataTableInput\n class=\"border-r-transparent\"\n :environment\n :modelValue=\"flow.refreshUrl ?? ''\"\n :placeholder=\"refreshUrlPlaceholder\"\n @update:modelValue=\"(v) => handleOauth2Update({ refreshUrl: v })\">\n Refresh URL\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow class=\"min-w-full\">\n <div class=\"flex h-8 items-center justify-end gap-2 border-t\">\n <ScalarButton\n v-if=\"supportsRefreshToken\"\n class=\"p-0 px-2 py-0.5\"\n :loader\n size=\"sm\"\n variant=\"outlined\"\n @click=\"handleRefresh\">\n Refresh\n </ScalarButton>\n <ScalarButton\n class=\"mr-1 p-0 px-2 py-0.5\"\n :disabled=\"loader.isLoading\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"handleClearAccessTokens\">\n Clear\n </ScalarButton>\n </div>\n </DataTableRow>\n </template>\n\n <!-- Authorization Form: Shows when user needs to authorize -->\n <template v-else>\n <DataTableRow>\n <RequestAuthDataTableInput\n v-if=\"'authorizationUrl' in flow\"\n containerClass=\"border-r-0\"\n :environment\n :modelValue=\"flow['x-scalar-secret-auth-url'] ?? ''\"\n placeholder=\"https://galaxy.scalar.com/authorize\"\n @update:modelValue=\"\n (v) => {\n handleOauth2SecretsUpdate({ 'x-scalar-secret-auth-url': v })\n handleOauth2Update({ authorizationUrl: v })\n }\n \">\n Auth URL\n </RequestAuthDataTableInput>\n\n <RequestAuthDataTableInput\n v-if=\"'tokenUrl' in flow\"\n :environment\n :modelValue=\"flow['x-scalar-secret-token-url'] ?? ''\"\n placeholder=\"https://galaxy.scalar.com/token\"\n @update:modelValue=\"\n (v) => {\n handleOauth2SecretsUpdate({ 'x-scalar-secret-token-url': v })\n handleOauth2Update({ tokenUrl: v })\n }\n \">\n Token URL\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"'x-scalar-secret-redirect-uri' in flow\">\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"flow['x-scalar-secret-redirect-uri']\"\n placeholder=\"Optional redirect URL\"\n @update:modelValue=\"\n (v) => {\n hasHandledRedirectPrefill = true\n handleOauth2SecretsUpdate({ 'x-scalar-secret-redirect-uri': v })\n }\n \">\n Redirect URL\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <template\n v-if=\"\n 'x-scalar-secret-username' in flow && 'x-scalar-secret-password' in flow\n \">\n <DataTableRow>\n <RequestAuthDataTableInput\n class=\"text-c-2\"\n :environment\n :modelValue=\"flow['x-scalar-secret-username']\"\n placeholder=\"janedoe\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-username': v })\n \">\n Username\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow>\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"flow['x-scalar-secret-password']\"\n placeholder=\"********\"\n type=\"password\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-password': v })\n \">\n Password\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n\n <DataTableRow>\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"flow['x-scalar-secret-client-id']\"\n placeholder=\"12345\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-client-id': v })\n \">\n Client ID\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"'x-scalar-secret-client-secret' in flow\">\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"flow['x-scalar-secret-client-secret']\"\n placeholder=\"XYZ123\"\n type=\"password\"\n @update:modelValue=\"\n (v) =>\n handleOauth2SecretsUpdate({ 'x-scalar-secret-client-secret': v })\n \">\n Client Secret\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"'x-usePkce' in flow\">\n <RequestAuthDataTableInput\n :enum=\"pkceOptions\"\n :environment\n :modelValue=\"flow['x-usePkce']\"\n readOnly\n @update:modelValue=\"\n (v) =>\n handleOauth2Update({\n 'x-usePkce': v as XusePkce['x-usePkce'],\n })\n \">\n Use PKCE\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <!-- Credentials Location -->\n <DataTableRow v-if=\"type !== 'implicit'\">\n <RequestAuthDataTableInput\n :enum=\"['header', 'body']\"\n :environment\n :modelValue=\"\n (flow as NonImplicitFlow)['x-scalar-credentials-location'] || 'header'\n \"\n placeholder=\"header\"\n readOnly\n @update:modelValue=\"(v) => handleSecretLocationUpdate(v)\">\n Credentials Location\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <!-- Scopes -->\n <DataTableRow>\n <OAuthScopesInput\n :flow\n :flowType=\"type\"\n :selectedScopes\n @update:selectedScopes=\"(v) => emits('update:selectedScopes', v)\" />\n </DataTableRow>\n\n <DataTableRow class=\"min-w-full\">\n <div class=\"flex h-8 w-full items-center justify-end border-t\">\n <!-- Allow clearing the oauth section and going back to discovery -->\n <ScalarButton\n v-if=\"scheme.type === 'openIdConnect'\"\n class=\"mr-1 p-0 px-2 py-0.5\"\n :disabled=\"loader.isLoading\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"clearOauth2Secrets\">\n Clear\n </ScalarButton>\n\n <ScalarButton\n class=\"mr-0.75 p-0 px-2 py-0.5\"\n :loader\n size=\"sm\"\n variant=\"outlined\"\n @click=\"handleAuthorize\">\n Authorize\n </ScalarButton>\n </div>\n </DataTableRow>\n </template>\n</template>\n"],"mappings":""}
import DataTableRow_default from "../../../components/data-table/DataTableRow.vue.js";
import OAuthScopesInput_default from "./OAuthScopesInput.vue.js";
import { authorizeOauth2 } from "../helpers/oauth.js";
import { authorizeOauth2, refreshOauth2Token } from "../helpers/oauth.js";
import { resolveDefaultOAuth2RedirectUri } from "../helpers/resolve-default-oauth2-redirect-url.js";

@@ -56,10 +56,37 @@ import RequestAuthDataTableInput_default from "./RequestAuthDataTableInput.vue.js";

/** Clears the flow secrets */
const clearOauth2Secrets = () => __props.eventBus.emit("auth:clear:security-scheme-secrets", { name: __props.name });
/** Track if we have set the redirect uri */
const hasPrefilledRedirectUri = ref(false);
const clearOauth2Secrets = () => {
if (loader.isLoading) return;
__props.eventBus.emit("auth:clear:security-scheme-secrets", { name: __props.name });
};
/** Clears stored access and refresh tokens (authorized state) */
const handleClearAccessTokens = () => {
if (loader.isLoading) return;
handleOauth2SecretsUpdate({
"x-scalar-secret-token": "",
"x-scalar-secret-refresh-token": ""
});
};
/** Track redirect URI prefill per flow instance to support document switching */
const prefilledFlowIdentity = ref(null);
const hasHandledRedirectPrefill = ref(false);
const resolveFlowIdentity = (currentFlow) => JSON.stringify({
type: __props.type,
authorizationUrl: currentFlow && "authorizationUrl" in currentFlow ? currentFlow.authorizationUrl : "",
tokenUrl: currentFlow && "tokenUrl" in currentFlow ? currentFlow.tokenUrl : "",
refreshUrl: currentFlow?.refreshUrl ?? "",
scopes: Object.keys(currentFlow?.scopes ?? {})
});
/** Default the redirect-uri to the current origin if we have access to window */
watch(() => flow.value["x-scalar-secret-redirect-uri"], (newRedirectUri) => {
watch(() => flow.value, (currentFlow) => {
if (!currentFlow || !("x-scalar-secret-redirect-uri" in currentFlow)) return;
const flowIdentity = resolveFlowIdentity(currentFlow);
if (prefilledFlowIdentity.value !== flowIdentity) {
prefilledFlowIdentity.value = flowIdentity;
hasHandledRedirectPrefill.value = false;
}
if (hasHandledRedirectPrefill.value) return;
const newRedirectUri = currentFlow["x-scalar-secret-redirect-uri"];
const defaultRedirectUri = resolveDefaultOAuth2RedirectUri(__props.options);
if (hasPrefilledRedirectUri.value || newRedirectUri || !defaultRedirectUri || !("x-scalar-secret-redirect-uri" in flow.value)) return;
hasPrefilledRedirectUri.value = true;
hasHandledRedirectPrefill.value = true;
if (newRedirectUri || !defaultRedirectUri) return;
handleOauth2SecretsUpdate({ "x-scalar-secret-redirect-uri": defaultRedirectUri });

@@ -85,2 +112,30 @@ }, { immediate: true });

};
/** Whether the current flow supports refreshing the access token */
const supportsRefreshToken = computed(() => __props.type !== "implicit");
/**
* Refresh URL placeholder, shows tokenUrl as hint if refreshUrl is not specified.
* This helps users understand that tokenUrl will be used as fallback.
*/
const refreshUrlPlaceholder = computed(() => {
if ("tokenUrl" in flow.value && flow.value.tokenUrl) return flow.value.tokenUrl;
return "https://galaxy.scalar.com/oauth/refresh";
});
/**
* Uses the stored refresh token to obtain a new access token
* via grant_type=refresh_token.
*/
const handleRefresh = async () => {
if (loader.isLoading || __props.type === "implicit") return;
loader.start();
const [error, tokens] = await refreshOauth2Token(__props.flows, __props.type, __props.proxyUrl, __props.server, getEnvironmentVariables(__props.environment));
await loader.clear();
if (tokens?.accessToken) handleOauth2SecretsUpdate({
"x-scalar-secret-token": tokens.accessToken,
...tokens.refreshToken ? { "x-scalar-secret-refresh-token": tokens.refreshToken } : {}
});
else {
console.error(error);
toast(error?.message ?? "Failed to refresh token", "error");
}
};
/** Updates the secret location */

@@ -93,31 +148,58 @@ const handleSecretLocationUpdate = (value) => {

return (_ctx, _cache) => {
return Boolean(flow.value["x-scalar-secret-token"]) ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createVNode(unref(DataTableRow_default), null, {
default: withCtx(() => [createVNode(RequestAuthDataTableInput_default, {
class: "border-r-transparent",
environment: __props.environment,
modelValue: flow.value["x-scalar-secret-token"],
placeholder: "QUxMIFlPVVIgQkFTRSBBUkUgQkVMT05HIFRPIFVT",
type: "password",
"onUpdate:modelValue": _cache[0] || (_cache[0] = (v) => handleOauth2SecretsUpdate({ "x-scalar-secret-token": v }))
}, {
default: withCtx(() => [..._cache[12] || (_cache[12] = [createTextVNode(" Access Token ", -1)])]),
return Boolean(flow.value["x-scalar-secret-token"]) ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
createVNode(unref(DataTableRow_default), null, {
default: withCtx(() => [createVNode(RequestAuthDataTableInput_default, {
class: "border-r-transparent",
environment: __props.environment,
modelValue: flow.value["x-scalar-secret-token"],
placeholder: "QUxMIFlPVVIgQkFTRSBBUkUgQkVMT05HIFRPIFVT",
type: "password",
"onUpdate:modelValue": _cache[0] || (_cache[0] = (v) => handleOauth2SecretsUpdate({ "x-scalar-secret-token": v }))
}, {
default: withCtx(() => [..._cache[12] || (_cache[12] = [createTextVNode(" Access Token ", -1)])]),
_: 1
}, 8, ["environment", "modelValue"])]),
_: 1
}, 8, ["environment", "modelValue"])]),
_: 1
}), createVNode(unref(DataTableRow_default), { class: "min-w-full" }, {
default: withCtx(() => [createElementVNode("div", _hoisted_1, [createVNode(unref(ScalarButton), {
class: "mr-1 p-0 px-2 py-0.5",
loader: unref(loader),
size: "sm",
variant: "outlined",
onClick: _cache[1] || (_cache[1] = () => handleOauth2SecretsUpdate({
"x-scalar-secret-token": "",
"x-scalar-secret-refresh-token": ""
}))
}, {
default: withCtx(() => [..._cache[13] || (_cache[13] = [createTextVNode(" Clear ", -1)])]),
}),
supportsRefreshToken.value ? (openBlock(), createBlock(unref(DataTableRow_default), { key: 0 }, {
default: withCtx(() => [createVNode(RequestAuthDataTableInput_default, {
class: "border-r-transparent",
environment: __props.environment,
modelValue: flow.value.refreshUrl ?? "",
placeholder: refreshUrlPlaceholder.value,
"onUpdate:modelValue": _cache[1] || (_cache[1] = (v) => handleOauth2Update({ refreshUrl: v }))
}, {
default: withCtx(() => [..._cache[13] || (_cache[13] = [createTextVNode(" Refresh URL ", -1)])]),
_: 1
}, 8, [
"environment",
"modelValue",
"placeholder"
])]),
_: 1
}, 8, ["loader"])])]),
_: 1
})], 64)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
})) : createCommentVNode("", true),
createVNode(unref(DataTableRow_default), { class: "min-w-full" }, {
default: withCtx(() => [createElementVNode("div", _hoisted_1, [supportsRefreshToken.value ? (openBlock(), createBlock(unref(ScalarButton), {
key: 0,
class: "p-0 px-2 py-0.5",
loader: unref(loader),
size: "sm",
variant: "outlined",
onClick: handleRefresh
}, {
default: withCtx(() => [..._cache[14] || (_cache[14] = [createTextVNode(" Refresh ", -1)])]),
_: 1
}, 8, ["loader"])) : createCommentVNode("", true), createVNode(unref(ScalarButton), {
class: "mr-1 p-0 px-2 py-0.5",
disabled: unref(loader).isLoading,
size: "sm",
variant: "outlined",
onClick: handleClearAccessTokens
}, {
default: withCtx(() => [..._cache[15] || (_cache[15] = [createTextVNode(" Clear ", -1)])]),
_: 1
}, 8, ["disabled"])])]),
_: 1
})
], 64)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
createVNode(unref(DataTableRow_default), null, {

@@ -135,3 +217,3 @@ default: withCtx(() => ["authorizationUrl" in flow.value ? (openBlock(), createBlock(RequestAuthDataTableInput_default, {

}, {
default: withCtx(() => [..._cache[14] || (_cache[14] = [createTextVNode(" Auth URL ", -1)])]),
default: withCtx(() => [..._cache[16] || (_cache[16] = [createTextVNode(" Auth URL ", -1)])]),
_: 1

@@ -148,3 +230,3 @@ }, 8, ["environment", "modelValue"])) : createCommentVNode("", true), "tokenUrl" in flow.value ? (openBlock(), createBlock(RequestAuthDataTableInput_default, {

}, {
default: withCtx(() => [..._cache[15] || (_cache[15] = [createTextVNode(" Token URL ", -1)])]),
default: withCtx(() => [..._cache[17] || (_cache[17] = [createTextVNode(" Token URL ", -1)])]),
_: 1

@@ -158,8 +240,9 @@ }, 8, ["environment", "modelValue"])) : createCommentVNode("", true)]),

modelValue: flow.value["x-scalar-secret-redirect-uri"],
placeholder: "https://galaxy.scalar.com/callback",
placeholder: "Optional redirect URL",
"onUpdate:modelValue": _cache[4] || (_cache[4] = (v) => {
hasHandledRedirectPrefill.value = true;
handleOauth2SecretsUpdate({ "x-scalar-secret-redirect-uri": v });
})
}, {
default: withCtx(() => [..._cache[16] || (_cache[16] = [createTextVNode(" Redirect URL ", -1)])]),
default: withCtx(() => [..._cache[18] || (_cache[18] = [createTextVNode(" Redirect URL ", -1)])]),
_: 1

@@ -177,3 +260,3 @@ }, 8, ["environment", "modelValue"])]),

}, {
default: withCtx(() => [..._cache[17] || (_cache[17] = [createTextVNode(" Username ", -1)])]),
default: withCtx(() => [..._cache[19] || (_cache[19] = [createTextVNode(" Username ", -1)])]),
_: 1

@@ -190,3 +273,3 @@ }, 8, ["environment", "modelValue"])]),

}, {
default: withCtx(() => [..._cache[18] || (_cache[18] = [createTextVNode(" Password ", -1)])]),
default: withCtx(() => [..._cache[20] || (_cache[20] = [createTextVNode(" Password ", -1)])]),
_: 1

@@ -203,3 +286,3 @@ }, 8, ["environment", "modelValue"])]),

}, {
default: withCtx(() => [..._cache[19] || (_cache[19] = [createTextVNode(" Client ID ", -1)])]),
default: withCtx(() => [..._cache[21] || (_cache[21] = [createTextVNode(" Client ID ", -1)])]),
_: 1

@@ -217,3 +300,3 @@ }, 8, ["environment", "modelValue"])]),

}, {
default: withCtx(() => [..._cache[20] || (_cache[20] = [createTextVNode(" Client Secret ", -1)])]),
default: withCtx(() => [..._cache[22] || (_cache[22] = [createTextVNode(" Client Secret ", -1)])]),
_: 1

@@ -231,3 +314,3 @@ }, 8, ["environment", "modelValue"])]),

}, {
default: withCtx(() => [..._cache[21] || (_cache[21] = [createTextVNode(" Use PKCE ", -1)])]),
default: withCtx(() => [..._cache[23] || (_cache[23] = [createTextVNode(" Use PKCE ", -1)])]),
_: 1

@@ -250,3 +333,3 @@ }, 8, [

}, {
default: withCtx(() => [..._cache[22] || (_cache[22] = [createTextVNode(" Credentials Location ", -1)])]),
default: withCtx(() => [..._cache[24] || (_cache[24] = [createTextVNode(" Credentials Location ", -1)])]),
_: 1

@@ -273,3 +356,3 @@ }, 8, ["environment", "modelValue"])]),

class: "mr-1 p-0 px-2 py-0.5",
loader: unref(loader),
disabled: unref(loader).isLoading,
size: "sm",

@@ -279,5 +362,5 @@ variant: "outlined",

}, {
default: withCtx(() => [..._cache[23] || (_cache[23] = [createTextVNode(" Clear ", -1)])]),
default: withCtx(() => [..._cache[25] || (_cache[25] = [createTextVNode(" Clear ", -1)])]),
_: 1
}, 8, ["loader"])) : createCommentVNode("", true), createVNode(unref(ScalarButton), {
}, 8, ["disabled"])) : createCommentVNode("", true), createVNode(unref(ScalarButton), {
class: "mr-0.75 p-0 px-2 py-0.5",

@@ -289,3 +372,3 @@ loader: unref(loader),

}, {
default: withCtx(() => [..._cache[24] || (_cache[24] = [createTextVNode(" Authorize ", -1)])]),
default: withCtx(() => [..._cache[26] || (_cache[26] = [createTextVNode(" Authorize ", -1)])]),
_: 1

@@ -292,0 +375,0 @@ }, 8, ["loader"])])]),

@@ -1,1 +0,1 @@

{"version":3,"file":"OAuth2.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue"],"sourcesContent":["<script lang=\"ts\">\n/** Any config options required for the OAuth2 flow */\nexport type OAuth2Options = Pick<ApiClientConfiguration, 'oauth2RedirectUri'>\n</script>\n\n<script setup lang=\"ts\">\nimport { ScalarButton, useLoadingState } from '@scalar/components'\nimport type { ApiClientConfiguration } from '@scalar/types/api-reference'\nimport { pkceOptions } from '@scalar/types/entities'\nimport { useToasts } from '@scalar/use-toasts'\nimport type { SecretsOAuthFlows } from '@scalar/workspace-store/entities/auth'\nimport type {\n ApiReferenceEvents,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport {\n getEnvironmentVariables,\n type OAuthFlowAuthorizationCodeSecret,\n type OAuthFlowClientCredentialsSecret,\n type OAuthFlowPasswordSecret,\n type OAuthFlowsObjectSecret,\n type SecuritySchemeObjectSecret,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { XScalarCredentialsLocation } from '@scalar/workspace-store/schemas/extensions/security/x-scalar-credentials-location'\nimport { type XusePkce } from '@scalar/workspace-store/schemas/extensions/security/x-use-pkce'\nimport type {\n OAuthFlow,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, ref, watch } from 'vue'\n\nimport OAuthScopesInput from '@/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue'\nimport { authorizeOauth2 } from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth'\nimport { resolveDefaultOAuth2RedirectUri } from '@/v2/blocks/scalar-auth-selector-block/helpers/resolve-default-oauth2-redirect-url'\nimport { DataTableRow } from '@/v2/components/data-table'\n\nimport RequestAuthDataTableInput from './RequestAuthDataTableInput.vue'\n\nconst {\n environment,\n flows,\n type,\n scheme,\n selectedScopes: selectedScopesProp,\n server,\n proxyUrl,\n eventBus,\n name,\n options = {},\n} = defineProps<{\n /** Current environment configuration */\n environment: XScalarEnvironment\n /** OAuth flows */\n flows: OAuthFlowsObjectSecret\n /** Type of the OAuth flow */\n type: keyof OAuthFlowsObjectSecret\n /** Selected scopes */\n selectedScopes: string[]\n /** Security scheme */\n scheme: SecuritySchemeObjectSecret\n /** Current server configuration */\n server: ServerObject | null\n /** Proxy URL */\n proxyUrl: string\n /** Name of the security scheme */\n name: string\n /** Event bus for authentication updates */\n eventBus: WorkspaceEventBus\n /** Any config options required for the OAuth2 flow */\n options?: OAuth2Options\n}>()\n\nconst emits = defineEmits<{\n (\n e: 'update:selectedScopes',\n payload: Pick<\n ApiReferenceEvents['auth:update:selected-scopes'],\n 'scopes' | 'newScopePayload'\n >,\n ): void\n}>()\n\nconst loader = useLoadingState()\nconst { toast } = useToasts()\n\n/** The current OAuth flow based on the selected type */\nconst flow = computed(() => flows[type]!)\ntype NonImplicitFlow =\n | OAuthFlowPasswordSecret\n | OAuthFlowClientCredentialsSecret\n | OAuthFlowAuthorizationCodeSecret\n\n/** We filter selected scopes to only include scopes that are in this flow*/\nconst selectedScopes = computed(() =>\n selectedScopesProp.filter((scope) => scope in (flow.value.scopes ?? {})),\n)\n\n/** Updates the security scheme base */\nconst handleOauth2Update = (\n payload: Partial<OAuthFlow & XScalarCredentialsLocation>,\n): void => {\n // OpenIdConnect uses the secrets update for all\n if (scheme.type === 'openIdConnect') {\n return handleOauth2SecretsUpdate(payload)\n }\n\n eventBus.emit('auth:update:security-scheme', {\n payload: {\n type: scheme.type,\n flows: {\n [type]: payload,\n },\n },\n name,\n })\n}\n\n/** Updates the flow secrets */\nconst handleOauth2SecretsUpdate = (\n payload: Omit<Partial<SecretsOAuthFlows[keyof SecretsOAuthFlows]>, 'type'>,\n): void =>\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: {\n type: scheme.type,\n [type]: payload,\n },\n name,\n })\n\n/** Clears the flow secrets */\nconst clearOauth2Secrets = (): void =>\n eventBus.emit('auth:clear:security-scheme-secrets', {\n name,\n })\n\n/** Track if we have set the redirect uri */\nconst hasPrefilledRedirectUri = ref(false)\n\n/** Default the redirect-uri to the current origin if we have access to window */\nwatch(\n () =>\n (flow.value as OAuthFlowAuthorizationCodeSecret)[\n 'x-scalar-secret-redirect-uri'\n ],\n (newRedirectUri) => {\n const defaultRedirectUri = resolveDefaultOAuth2RedirectUri(options)\n\n if (\n hasPrefilledRedirectUri.value ||\n newRedirectUri ||\n !defaultRedirectUri ||\n !('x-scalar-secret-redirect-uri' in flow.value)\n ) {\n return\n }\n hasPrefilledRedirectUri.value = true\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-redirect-uri': defaultRedirectUri,\n })\n },\n { immediate: true },\n)\n\n/**\n * Authorizes the user using the specified OAuth flow.\n * Opens the appropriate OAuth dialog and/or performs the token exchange.\n */\nconst handleAuthorize = async (): Promise<void> => {\n if (loader.isLoading) {\n return\n }\n\n loader.start()\n\n const [error, tokens] = await authorizeOauth2(\n flows,\n type,\n selectedScopes.value,\n server,\n proxyUrl,\n getEnvironmentVariables(environment),\n )\n\n await loader.clear()\n\n if (tokens?.accessToken) {\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-token': tokens.accessToken,\n ...(tokens.refreshToken\n ? { 'x-scalar-secret-refresh-token': tokens.refreshToken }\n : {}),\n })\n } else {\n console.error(error)\n toast(error?.message ?? 'Failed to authorize', 'error')\n }\n}\n\n/** Updates the secret location */\nconst handleSecretLocationUpdate = (value: string): void => {\n const credentialsLocation = value === 'body' ? 'body' : 'header'\n\n if (scheme.type !== 'openIdConnect') {\n handleOauth2Update({\n 'x-scalar-credentials-location': credentialsLocation,\n })\n }\n\n handleOauth2SecretsUpdate({\n 'x-scalar-credentials-location': credentialsLocation,\n })\n}\n</script>\n\n<template>\n <!-- Access Token Display: Shows when user is already authorized -->\n <template v-if=\"Boolean(flow['x-scalar-secret-token'])\">\n <DataTableRow>\n <RequestAuthDataTableInput\n class=\"border-r-transparent\"\n :environment\n :modelValue=\"flow['x-scalar-secret-token']\"\n placeholder=\"QUxMIFlPVVIgQkFTRSBBUkUgQkVMT05HIFRPIFVT\"\n type=\"password\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-token': v })\n \">\n Access Token\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow class=\"min-w-full\">\n <div class=\"flex h-8 items-center justify-end gap-2 border-t\">\n <ScalarButton\n class=\"mr-1 p-0 px-2 py-0.5\"\n :loader\n size=\"sm\"\n variant=\"outlined\"\n @click=\"\n () =>\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-token': '',\n 'x-scalar-secret-refresh-token': '',\n })\n \">\n Clear\n </ScalarButton>\n </div>\n </DataTableRow>\n </template>\n\n <!-- Authorization Form: Shows when user needs to authorize -->\n <template v-else>\n <DataTableRow>\n <RequestAuthDataTableInput\n v-if=\"'authorizationUrl' in flow\"\n containerClass=\"border-r-0\"\n :environment\n :modelValue=\"flow['x-scalar-secret-auth-url'] ?? ''\"\n placeholder=\"https://galaxy.scalar.com/authorize\"\n @update:modelValue=\"\n (v) => {\n handleOauth2SecretsUpdate({ 'x-scalar-secret-auth-url': v })\n handleOauth2Update({ authorizationUrl: v })\n }\n \">\n Auth URL\n </RequestAuthDataTableInput>\n\n <RequestAuthDataTableInput\n v-if=\"'tokenUrl' in flow\"\n :environment\n :modelValue=\"flow['x-scalar-secret-token-url'] ?? ''\"\n placeholder=\"https://galaxy.scalar.com/token\"\n @update:modelValue=\"\n (v) => {\n handleOauth2SecretsUpdate({ 'x-scalar-secret-token-url': v })\n handleOauth2Update({ tokenUrl: v })\n }\n \">\n Token URL\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"'x-scalar-secret-redirect-uri' in flow\">\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"flow['x-scalar-secret-redirect-uri']\"\n placeholder=\"https://galaxy.scalar.com/callback\"\n @update:modelValue=\"\n (v) => {\n handleOauth2SecretsUpdate({ 'x-scalar-secret-redirect-uri': v })\n }\n \">\n Redirect URL\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <template\n v-if=\"\n 'x-scalar-secret-username' in flow && 'x-scalar-secret-password' in flow\n \">\n <DataTableRow>\n <RequestAuthDataTableInput\n class=\"text-c-2\"\n :environment\n :modelValue=\"flow['x-scalar-secret-username']\"\n placeholder=\"janedoe\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-username': v })\n \">\n Username\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow>\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"flow['x-scalar-secret-password']\"\n placeholder=\"********\"\n type=\"password\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-password': v })\n \">\n Password\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n\n <DataTableRow>\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"flow['x-scalar-secret-client-id']\"\n placeholder=\"12345\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-client-id': v })\n \">\n Client ID\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"'x-scalar-secret-client-secret' in flow\">\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"flow['x-scalar-secret-client-secret']\"\n placeholder=\"XYZ123\"\n type=\"password\"\n @update:modelValue=\"\n (v) =>\n handleOauth2SecretsUpdate({ 'x-scalar-secret-client-secret': v })\n \">\n Client Secret\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"'x-usePkce' in flow\">\n <RequestAuthDataTableInput\n :enum=\"pkceOptions\"\n :environment\n :modelValue=\"flow['x-usePkce']\"\n readOnly\n @update:modelValue=\"\n (v) =>\n handleOauth2Update({\n 'x-usePkce': v as XusePkce['x-usePkce'],\n })\n \">\n Use PKCE\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <!-- Credentials Location -->\n <DataTableRow v-if=\"type !== 'implicit'\">\n <RequestAuthDataTableInput\n :enum=\"['header', 'body']\"\n :environment\n :modelValue=\"\n (flow as NonImplicitFlow)['x-scalar-credentials-location'] || 'header'\n \"\n placeholder=\"header\"\n readOnly\n @update:modelValue=\"(v) => handleSecretLocationUpdate(v)\">\n Credentials Location\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <!-- Scopes -->\n <DataTableRow>\n <OAuthScopesInput\n :flow\n :flowType=\"type\"\n :selectedScopes\n @update:selectedScopes=\"(v) => emits('update:selectedScopes', v)\" />\n </DataTableRow>\n\n <DataTableRow class=\"min-w-full\">\n <div class=\"flex h-8 w-full items-center justify-end border-t\">\n <!-- Allow clearing the oauth section and going back to discovery -->\n <ScalarButton\n v-if=\"scheme.type === 'openIdConnect'\"\n class=\"mr-1 p-0 px-2 py-0.5\"\n :loader\n size=\"sm\"\n variant=\"outlined\"\n @click=\"clearOauth2Secrets\">\n Clear\n </ScalarButton>\n\n <ScalarButton\n class=\"mr-0.75 p-0 px-2 py-0.5\"\n :loader\n size=\"sm\"\n variant=\"outlined\"\n @click=\"handleAuthorize\">\n Authorize\n </ScalarButton>\n </div>\n </DataTableRow>\n </template>\n</template>\n"],"mappings":"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"}
{"version":3,"file":"OAuth2.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue"],"sourcesContent":["<script lang=\"ts\">\n/** Any config options required for the OAuth2 flow */\nexport type OAuth2Options = Pick<ApiClientConfiguration, 'oauth2RedirectUri'>\n</script>\n\n<script setup lang=\"ts\">\nimport { ScalarButton, useLoadingState } from '@scalar/components'\nimport type { ApiClientConfiguration } from '@scalar/types/api-reference'\nimport { pkceOptions } from '@scalar/types/entities'\nimport { useToasts } from '@scalar/use-toasts'\nimport type { SecretsOAuthFlows } from '@scalar/workspace-store/entities/auth'\nimport type {\n ApiReferenceEvents,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport {\n getEnvironmentVariables,\n type OAuthFlowAuthorizationCodeSecret,\n type OAuthFlowClientCredentialsSecret,\n type OAuthFlowPasswordSecret,\n type OAuthFlowsObjectSecret,\n type SecuritySchemeObjectSecret,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { XScalarCredentialsLocation } from '@scalar/workspace-store/schemas/extensions/security/x-scalar-credentials-location'\nimport { type XusePkce } from '@scalar/workspace-store/schemas/extensions/security/x-use-pkce'\nimport type {\n OAuthFlow,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, ref, watch } from 'vue'\n\nimport OAuthScopesInput from '@/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue'\nimport {\n authorizeOauth2,\n refreshOauth2Token,\n} from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth'\nimport { resolveDefaultOAuth2RedirectUri } from '@/v2/blocks/scalar-auth-selector-block/helpers/resolve-default-oauth2-redirect-url'\nimport { DataTableRow } from '@/v2/components/data-table'\n\nimport RequestAuthDataTableInput from './RequestAuthDataTableInput.vue'\n\nconst {\n environment,\n flows,\n type,\n scheme,\n selectedScopes: selectedScopesProp,\n server,\n proxyUrl,\n eventBus,\n name,\n options = {},\n} = defineProps<{\n /** Current environment configuration */\n environment: XScalarEnvironment\n /** OAuth flows */\n flows: OAuthFlowsObjectSecret\n /** Type of the OAuth flow */\n type: keyof OAuthFlowsObjectSecret\n /** Selected scopes */\n selectedScopes: string[]\n /** Security scheme */\n scheme: SecuritySchemeObjectSecret\n /** Current server configuration */\n server: ServerObject | null\n /** Proxy URL */\n proxyUrl: string\n /** Name of the security scheme */\n name: string\n /** Event bus for authentication updates */\n eventBus: WorkspaceEventBus\n /** Any config options required for the OAuth2 flow */\n options?: OAuth2Options\n}>()\n\nconst emits = defineEmits<{\n (\n e: 'update:selectedScopes',\n payload: Pick<\n ApiReferenceEvents['auth:update:selected-scopes'],\n 'scopes' | 'newScopePayload'\n >,\n ): void\n}>()\n\nconst loader = useLoadingState()\nconst { toast } = useToasts()\n\n/** The current OAuth flow based on the selected type */\nconst flow = computed(() => flows[type]!)\ntype NonImplicitFlow =\n | OAuthFlowPasswordSecret\n | OAuthFlowClientCredentialsSecret\n | OAuthFlowAuthorizationCodeSecret\n\n/** We filter selected scopes to only include scopes that are in this flow*/\nconst selectedScopes = computed(() =>\n selectedScopesProp.filter((scope) => scope in (flow.value.scopes ?? {})),\n)\n\n/** Updates the security scheme base */\nconst handleOauth2Update = (\n payload: Partial<OAuthFlow & XScalarCredentialsLocation>,\n): void => {\n // OpenIdConnect uses the secrets update for all\n if (scheme.type === 'openIdConnect') {\n return handleOauth2SecretsUpdate(payload)\n }\n\n eventBus.emit('auth:update:security-scheme', {\n payload: {\n type: scheme.type,\n flows: {\n [type]: payload,\n },\n },\n name,\n })\n}\n\n/** Updates the flow secrets */\nconst handleOauth2SecretsUpdate = (\n payload: Omit<Partial<SecretsOAuthFlows[keyof SecretsOAuthFlows]>, 'type'>,\n): void =>\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: {\n type: scheme.type,\n [type]: payload,\n },\n name,\n })\n\n/** Clears the flow secrets */\nconst clearOauth2Secrets = (): void => {\n if (loader.isLoading) {\n return\n }\n eventBus.emit('auth:clear:security-scheme-secrets', {\n name,\n })\n}\n\n/** Clears stored access and refresh tokens (authorized state) */\nconst handleClearAccessTokens = (): void => {\n if (loader.isLoading) {\n return\n }\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-token': '',\n 'x-scalar-secret-refresh-token': '',\n })\n}\n\n/** Track redirect URI prefill per flow instance to support document switching */\nconst prefilledFlowIdentity = ref<string | null>(null)\nconst hasHandledRedirectPrefill = ref(false)\n\nconst resolveFlowIdentity = (\n currentFlow: OAuthFlowsObjectSecret[keyof OAuthFlowsObjectSecret] | undefined,\n): string =>\n JSON.stringify({\n type,\n authorizationUrl:\n currentFlow && 'authorizationUrl' in currentFlow\n ? currentFlow.authorizationUrl\n : '',\n tokenUrl:\n currentFlow && 'tokenUrl' in currentFlow ? currentFlow.tokenUrl : '',\n refreshUrl: currentFlow?.refreshUrl ?? '',\n scopes: Object.keys(currentFlow?.scopes ?? {}),\n })\n\n/** Default the redirect-uri to the current origin if we have access to window */\nwatch(\n () => flow.value,\n (currentFlow) => {\n if (!currentFlow || !('x-scalar-secret-redirect-uri' in currentFlow)) {\n return\n }\n\n const flowIdentity = resolveFlowIdentity(currentFlow)\n if (prefilledFlowIdentity.value !== flowIdentity) {\n prefilledFlowIdentity.value = flowIdentity\n hasHandledRedirectPrefill.value = false\n }\n\n if (hasHandledRedirectPrefill.value) {\n return\n }\n\n const newRedirectUri = (currentFlow as OAuthFlowAuthorizationCodeSecret)[\n 'x-scalar-secret-redirect-uri'\n ]\n const defaultRedirectUri = resolveDefaultOAuth2RedirectUri(options)\n\n hasHandledRedirectPrefill.value = true\n\n if (newRedirectUri || !defaultRedirectUri) {\n return\n }\n\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-redirect-uri': defaultRedirectUri,\n })\n },\n { immediate: true },\n)\n\n/**\n * Authorizes the user using the specified OAuth flow.\n * Opens the appropriate OAuth dialog and/or performs the token exchange.\n */\nconst handleAuthorize = async (): Promise<void> => {\n if (loader.isLoading) {\n return\n }\n\n loader.start()\n\n const [error, tokens] = await authorizeOauth2(\n flows,\n type,\n selectedScopes.value,\n server,\n proxyUrl,\n getEnvironmentVariables(environment),\n )\n\n await loader.clear()\n\n if (tokens?.accessToken) {\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-token': tokens.accessToken,\n ...(tokens.refreshToken\n ? { 'x-scalar-secret-refresh-token': tokens.refreshToken }\n : {}),\n })\n } else {\n console.error(error)\n toast(error?.message ?? 'Failed to authorize', 'error')\n }\n}\n\n/** Whether the current flow supports refreshing the access token */\nconst supportsRefreshToken = computed(() => type !== 'implicit')\n\n/**\n * Refresh URL placeholder, shows tokenUrl as hint if refreshUrl is not specified.\n * This helps users understand that tokenUrl will be used as fallback.\n */\nconst refreshUrlPlaceholder = computed(() => {\n if ('tokenUrl' in flow.value && flow.value.tokenUrl) {\n return flow.value.tokenUrl\n }\n return 'https://galaxy.scalar.com/oauth/refresh'\n})\n\n/**\n * Uses the stored refresh token to obtain a new access token\n * via grant_type=refresh_token.\n */\nconst handleRefresh = async (): Promise<void> => {\n if (loader.isLoading || type === 'implicit') {\n return\n }\n\n loader.start()\n\n const [error, tokens] = await refreshOauth2Token(\n flows,\n type,\n proxyUrl,\n server,\n getEnvironmentVariables(environment),\n )\n\n await loader.clear()\n\n if (tokens?.accessToken) {\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-token': tokens.accessToken,\n ...(tokens.refreshToken\n ? { 'x-scalar-secret-refresh-token': tokens.refreshToken }\n : {}),\n })\n } else {\n console.error(error)\n toast(error?.message ?? 'Failed to refresh token', 'error')\n }\n}\n\n/** Updates the secret location */\nconst handleSecretLocationUpdate = (value: string): void => {\n const credentialsLocation = value === 'body' ? 'body' : 'header'\n\n if (scheme.type !== 'openIdConnect') {\n handleOauth2Update({\n 'x-scalar-credentials-location': credentialsLocation,\n })\n }\n\n handleOauth2SecretsUpdate({\n 'x-scalar-credentials-location': credentialsLocation,\n })\n}\n</script>\n\n<template>\n <!-- Access Token Display: Shows when user is already authorized -->\n <template v-if=\"Boolean(flow['x-scalar-secret-token'])\">\n <DataTableRow>\n <RequestAuthDataTableInput\n class=\"border-r-transparent\"\n :environment\n :modelValue=\"flow['x-scalar-secret-token']\"\n placeholder=\"QUxMIFlPVVIgQkFTRSBBUkUgQkVMT05HIFRPIFVT\"\n type=\"password\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-token': v })\n \">\n Access Token\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"supportsRefreshToken\">\n <RequestAuthDataTableInput\n class=\"border-r-transparent\"\n :environment\n :modelValue=\"flow.refreshUrl ?? ''\"\n :placeholder=\"refreshUrlPlaceholder\"\n @update:modelValue=\"(v) => handleOauth2Update({ refreshUrl: v })\">\n Refresh URL\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow class=\"min-w-full\">\n <div class=\"flex h-8 items-center justify-end gap-2 border-t\">\n <ScalarButton\n v-if=\"supportsRefreshToken\"\n class=\"p-0 px-2 py-0.5\"\n :loader\n size=\"sm\"\n variant=\"outlined\"\n @click=\"handleRefresh\">\n Refresh\n </ScalarButton>\n <ScalarButton\n class=\"mr-1 p-0 px-2 py-0.5\"\n :disabled=\"loader.isLoading\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"handleClearAccessTokens\">\n Clear\n </ScalarButton>\n </div>\n </DataTableRow>\n </template>\n\n <!-- Authorization Form: Shows when user needs to authorize -->\n <template v-else>\n <DataTableRow>\n <RequestAuthDataTableInput\n v-if=\"'authorizationUrl' in flow\"\n containerClass=\"border-r-0\"\n :environment\n :modelValue=\"flow['x-scalar-secret-auth-url'] ?? ''\"\n placeholder=\"https://galaxy.scalar.com/authorize\"\n @update:modelValue=\"\n (v) => {\n handleOauth2SecretsUpdate({ 'x-scalar-secret-auth-url': v })\n handleOauth2Update({ authorizationUrl: v })\n }\n \">\n Auth URL\n </RequestAuthDataTableInput>\n\n <RequestAuthDataTableInput\n v-if=\"'tokenUrl' in flow\"\n :environment\n :modelValue=\"flow['x-scalar-secret-token-url'] ?? ''\"\n placeholder=\"https://galaxy.scalar.com/token\"\n @update:modelValue=\"\n (v) => {\n handleOauth2SecretsUpdate({ 'x-scalar-secret-token-url': v })\n handleOauth2Update({ tokenUrl: v })\n }\n \">\n Token URL\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"'x-scalar-secret-redirect-uri' in flow\">\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"flow['x-scalar-secret-redirect-uri']\"\n placeholder=\"Optional redirect URL\"\n @update:modelValue=\"\n (v) => {\n hasHandledRedirectPrefill = true\n handleOauth2SecretsUpdate({ 'x-scalar-secret-redirect-uri': v })\n }\n \">\n Redirect URL\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <template\n v-if=\"\n 'x-scalar-secret-username' in flow && 'x-scalar-secret-password' in flow\n \">\n <DataTableRow>\n <RequestAuthDataTableInput\n class=\"text-c-2\"\n :environment\n :modelValue=\"flow['x-scalar-secret-username']\"\n placeholder=\"janedoe\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-username': v })\n \">\n Username\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow>\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"flow['x-scalar-secret-password']\"\n placeholder=\"********\"\n type=\"password\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-password': v })\n \">\n Password\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n\n <DataTableRow>\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"flow['x-scalar-secret-client-id']\"\n placeholder=\"12345\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-client-id': v })\n \">\n Client ID\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"'x-scalar-secret-client-secret' in flow\">\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"flow['x-scalar-secret-client-secret']\"\n placeholder=\"XYZ123\"\n type=\"password\"\n @update:modelValue=\"\n (v) =>\n handleOauth2SecretsUpdate({ 'x-scalar-secret-client-secret': v })\n \">\n Client Secret\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"'x-usePkce' in flow\">\n <RequestAuthDataTableInput\n :enum=\"pkceOptions\"\n :environment\n :modelValue=\"flow['x-usePkce']\"\n readOnly\n @update:modelValue=\"\n (v) =>\n handleOauth2Update({\n 'x-usePkce': v as XusePkce['x-usePkce'],\n })\n \">\n Use PKCE\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <!-- Credentials Location -->\n <DataTableRow v-if=\"type !== 'implicit'\">\n <RequestAuthDataTableInput\n :enum=\"['header', 'body']\"\n :environment\n :modelValue=\"\n (flow as NonImplicitFlow)['x-scalar-credentials-location'] || 'header'\n \"\n placeholder=\"header\"\n readOnly\n @update:modelValue=\"(v) => handleSecretLocationUpdate(v)\">\n Credentials Location\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <!-- Scopes -->\n <DataTableRow>\n <OAuthScopesInput\n :flow\n :flowType=\"type\"\n :selectedScopes\n @update:selectedScopes=\"(v) => emits('update:selectedScopes', v)\" />\n </DataTableRow>\n\n <DataTableRow class=\"min-w-full\">\n <div class=\"flex h-8 w-full items-center justify-end border-t\">\n <!-- Allow clearing the oauth section and going back to discovery -->\n <ScalarButton\n v-if=\"scheme.type === 'openIdConnect'\"\n class=\"mr-1 p-0 px-2 py-0.5\"\n :disabled=\"loader.isLoading\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"clearOauth2Secrets\">\n Clear\n </ScalarButton>\n\n <ScalarButton\n class=\"mr-0.75 p-0 px-2 py-0.5\"\n :loader\n size=\"sm\"\n variant=\"outlined\"\n @click=\"handleAuthorize\">\n Authorize\n </ScalarButton>\n </div>\n </DataTableRow>\n </template>\n</template>\n"],"mappings":"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"}

@@ -7,2 +7,3 @@ import { type ModalState } from '@scalar/components';

declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
cancel: () => any;
submit: (scopeData: {

@@ -12,4 +13,4 @@ name: string;

}) => any;
cancel: () => any;
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
onCancel?: (() => any) | undefined;
onSubmit?: ((scopeData: {

@@ -19,3 +20,2 @@ name: string;

}) => any) | undefined;
onCancel?: (() => any) | undefined;
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;

@@ -22,0 +22,0 @@ declare const _default: typeof __VLS_export;

@@ -1,1 +0,1 @@

{"version":3,"file":"OAuthScopesAddModal.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/OAuthScopesAddModal.vue"],"names":[],"mappings":"AAuGA,OAAO,EAAe,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAA;AASjE,KAAK,WAAW,GAAG;IACjB,KAAK,EAAE,UAAU,CAAA;IACjB,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB,CAAC;AAmLF,QAAA,MAAM,YAAY;;cA1KN,MAAM;qBACC,MAAM;;;;;cADb,MAAM;qBACC,MAAM;;;kFA4KvB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
{"version":3,"file":"OAuthScopesAddModal.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/OAuthScopesAddModal.vue"],"names":[],"mappings":"AAuGA,OAAO,EAAe,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAA;AASjE,KAAK,WAAW,GAAG;IACjB,KAAK,EAAE,UAAU,CAAA;IACjB,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB,CAAC;AAmLF,QAAA,MAAM,YAAY;;;cA1KN,MAAM;qBACC,MAAM;;;;;cADb,MAAM;qBACC,MAAM;;kFA4KvB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}

@@ -1,1 +0,1 @@

{"version":3,"file":"extract-security-scheme-secrets.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/extract-security-scheme-secrets.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAC5D,OAAO,KAAK,EAAE,SAAS,EAA2C,MAAM,uCAAuC,CAAA;AAC/G,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iDAAiD,CAAA;AAClF,OAAO,KAAK,EAUV,0BAA0B,EAC3B,MAAM,yCAAyC,CAAA;AAQhD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8DAA8D,CAAA;AAExG,wGAAwG;AACxG,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,GAAG,WAAW,CAAC,cAAc,CAAC,CAAA;AAyKjF,6DAA6D;AAC7D,eAAO,MAAM,4BAA4B,GAEvC,QAAQ,oBAAoB,GAAG,WAAW,CAAC,cAAc,CAAC,EAC1D,WAAW,SAAS,EACpB,MAAM,MAAM,EACZ,cAAc,MAAM,KACnB,0BA2DF,CAAA"}
{"version":3,"file":"extract-security-scheme-secrets.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/extract-security-scheme-secrets.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAC5D,OAAO,KAAK,EAAE,SAAS,EAA2C,MAAM,uCAAuC,CAAA;AAC/G,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iDAAiD,CAAA;AAClF,OAAO,KAAK,EAUV,0BAA0B,EAC3B,MAAM,yCAAyC,CAAA;AAQhD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8DAA8D,CAAA;AAExG,wGAAwG;AACxG,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,GAAG,WAAW,CAAC,cAAc,CAAC,CAAA;AAkLjF,6DAA6D;AAC7D,eAAO,MAAM,4BAA4B,GAEvC,QAAQ,oBAAoB,GAAG,WAAW,CAAC,cAAc,CAAC,EAC1D,WAAW,SAAS,EACpB,MAAM,MAAM,EACZ,cAAc,MAAM,KACnB,0BA2DF,CAAA"}

@@ -8,2 +8,4 @@ import type { ErrorResponse } from '@scalar/helpers/errors/normalize-error';

};
/** Flow types that support token refresh (all except implicit) */
type RefreshableFlows = Exclude<keyof OAuthFlowsObjectSecret, 'implicit'>;
/**

@@ -21,2 +23,16 @@ * Authorize oauth2 flow

environmentVariables?: Record<string, string>) => Promise<ErrorResponse<OAuth2Tokens>>;
/**
* Exchange a refresh token for a new access token using the `grant_type=refresh_token` flow.
*
* Uses the stored refresh token, client credentials, and the token URL (or refreshUrl when available)
* to request fresh tokens from the authorization server per RFC 6749 Section 6.
*/
export declare const refreshOauth2Token: (flows: OAuthFlowsObjectSecret, type: RefreshableFlows,
/** If we want to use the proxy */
proxyUrl: string,
/** We use the active server to set a base for relative URLs */
activeServer: ServerObject | null,
/** Flattened environment variables used to resolve server URL templates */
environmentVariables?: Record<string, string>) => Promise<ErrorResponse<OAuth2Tokens>>;
export {};
//# sourceMappingURL=oauth.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/oauth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAK3E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAA;AAErF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAA;AAYhG,MAAM,MAAM,YAAY,GAAG;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AA4DD;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAC1B,OAAO,sBAAsB,EAC7B,MAAM,MAAM,sBAAsB,EAClC,gBAAgB,MAAM,EAAE;AACxB,wEAAwE;AACxE,cAAc,YAAY,GAAG,IAAI;AACjC,kCAAkC;AAClC,UAAU,MAAM;AAChB,6FAA6F;AAC7F,uBAAsB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,KAChD,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CAwLrC,CAAA"}
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/oauth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAK3E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAA;AAErF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAA;AAYhG,MAAM,MAAM,YAAY,GAAG;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAED,kEAAkE;AAClE,KAAK,gBAAgB,GAAG,OAAO,CAAC,MAAM,sBAAsB,EAAE,UAAU,CAAC,CAAA;AA4DzE;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAC1B,OAAO,sBAAsB,EAC7B,MAAM,MAAM,sBAAsB,EAClC,gBAAgB,MAAM,EAAE;AACxB,wEAAwE;AACxE,cAAc,YAAY,GAAG,IAAI;AACjC,kCAAkC;AAClC,UAAU,MAAM;AAChB,6FAA6F;AAC7F,uBAAsB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,KAChD,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CAwLrC,CAAA;AA2HD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,GAC7B,OAAO,sBAAsB,EAC7B,MAAM,gBAAgB;AACtB,kCAAkC;AAClC,UAAU,MAAM;AAChB,+DAA+D;AAC/D,cAAc,YAAY,GAAG,IAAI;AACjC,2EAA2E;AAC3E,uBAAsB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,KAChD,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CA+ErC,CAAA"}

@@ -184,5 +184,47 @@ import { makeUrlAbsolute } from "@scalar/helpers/url/make-url-absolute";

};
/**
* Exchange a refresh token for a new access token using the `grant_type=refresh_token` flow.
*
* Uses the stored refresh token, client credentials, and the token URL (or refreshUrl when available)
* to request fresh tokens from the authorization server per RFC 6749 Section 6.
*/
var refreshOauth2Token = async (flows, type, proxyUrl, activeServer, environmentVariables = {}) => {
const flow = flows[type];
if (!flow) return [/* @__PURE__ */ new Error("OAuth2 flow was not defined"), null];
const refreshToken = flow["x-scalar-secret-refresh-token"];
if (!refreshToken) return [/* @__PURE__ */ new Error("No refresh token available"), null];
const formData = new URLSearchParams();
formData.set("grant_type", "refresh_token");
formData.set("refresh_token", refreshToken);
const addCredentialsToBody = flow["x-scalar-credentials-location"] === "body";
const hasClientSecret = Boolean(flow["x-scalar-secret-client-secret"]);
if (addCredentialsToBody || type === "authorizationCode" && !hasClientSecret) formData.set("client_id", flow["x-scalar-secret-client-id"]);
if (addCredentialsToBody && hasClientSecret) formData.set("client_secret", flow["x-scalar-secret-client-secret"]);
if (flow["x-scalar-security-body"]) Object.entries(flow["x-scalar-security-body"]).forEach(([key, value]) => {
if (value !== void 0 && value !== null) formData.set(key, String(value));
});
try {
const headers = { "Content-Type": "application/x-www-form-urlencoded" };
if (!addCredentialsToBody && hasClientSecret) headers.Authorization = `Basic ${encode(`${flow["x-scalar-secret-client-id"]}:${flow["x-scalar-secret-client-secret"]}`)}`;
const absoluteRefreshUrl = makeUrlAbsolute(flow.refreshUrl || flow["x-scalar-secret-token-url"] || flow.tokenUrl, getActiveServerBase(activeServer, environmentVariables));
const url = shouldUseProxy(proxyUrl, absoluteRefreshUrl) ? `${proxyUrl}?${new URLSearchParams([["scalar_url", absoluteRefreshUrl]]).toString()}` : absoluteRefreshUrl;
const responseData = await (await fetch(url, {
method: "POST",
headers,
body: formData
})).json();
const accessToken = responseData[flow["x-tokenName"] || "access_token"];
const newRefreshToken = responseData.refresh_token;
if (!accessToken) return [new Error(responseData.error_description ?? responseData.error ?? "Token refresh failed"), null];
return [null, {
accessToken,
...typeof newRefreshToken === "string" ? { refreshToken: newRefreshToken } : { refreshToken }
}];
} catch {
return [/* @__PURE__ */ new Error("Failed to refresh the access token. Please re-authorize."), null];
}
};
//#endregion
export { authorizeOauth2 };
export { authorizeOauth2, refreshOauth2Token };
//# sourceMappingURL=oauth.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"oauth.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/oauth.ts"],"sourcesContent":["import type { ErrorResponse } from '@scalar/helpers/errors/normalize-error'\nimport { replaceEnvVariables, replacePathVariables } from '@scalar/helpers/regex/replace-variables'\nimport { isRelativePath } from '@scalar/helpers/url/is-relative-path'\nimport { makeUrlAbsolute } from '@scalar/helpers/url/make-url-absolute'\nimport { shouldUseProxy } from '@scalar/helpers/url/redirect-to-proxy'\nimport type { OAuthFlowsObjectSecret } from '@scalar/workspace-store/request-example'\nimport { getServerVariables } from '@scalar/workspace-store/request-example'\nimport type { ServerObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { encode, fromUint8Array } from 'js-base64'\n\n/** Oauth2 security schemes which are not implicit */\ntype NonImplicitFlows = Omit<OAuthFlowsObjectSecret, 'implicit'>\n\ntype PKCEState = {\n codeVerifier: string\n codeChallenge: string\n codeChallengeMethod: string\n}\n\nexport type OAuth2Tokens = {\n accessToken: string\n refreshToken?: string\n}\n\nconst getServerUrl = (activeServer: ServerObject | null, environmentVariables: Record<string, string> = {}) => {\n return replaceEnvVariables(\n replacePathVariables(activeServer?.url ?? '', getServerVariables(activeServer)),\n environmentVariables,\n )\n}\n\nconst getActiveServerBase = (activeServer: ServerObject | null, environmentVariables: Record<string, string> = {}) => {\n const serverUrl = getServerUrl(activeServer, environmentVariables)\n\n if (!serverUrl) {\n return {}\n }\n\n if (isRelativePath(serverUrl)) {\n return typeof window === 'undefined' ? {} : { basePath: serverUrl }\n }\n\n return { baseUrl: serverUrl }\n}\n\n/**\n * Generates a random string for PKCE code verifier\n *\n * @see https://www.rfc-editor.org/rfc/rfc7636#page-8\n */\nconst generateCodeVerifier = (): string => {\n // Generate 32 random bytes\n const buffer = new Uint8Array(32)\n crypto.getRandomValues(buffer)\n\n // Base64URL encode the bytes\n return fromUint8Array(buffer, true)\n}\n\n/**\n * Creates a code challenge from the code verifier\n */\nconst generateCodeChallenge = async (verifier: string, encoding: 'SHA-256' | 'plain'): Promise<string> => {\n if (encoding === 'plain') {\n return verifier\n }\n\n // If crypto.subtle.digest is not a function, we cannot use SHA-256\n if (typeof crypto?.subtle?.digest !== 'function') {\n console.warn('SHA-256 is only supported when using https, using a plain text code challenge instead.')\n return verifier\n }\n\n // ASCII encoding is just taking the lower 8 bits of each character\n const encoder = new TextEncoder()\n const data = encoder.encode(verifier)\n const digest = await crypto.subtle.digest('SHA-256', data)\n\n // Base64URL encode the bytes\n return fromUint8Array(new Uint8Array(digest), true)\n}\n\n/**\n * Authorize oauth2 flow\n *\n * @returns the resolved oauth2 tokens\n */\nexport const authorizeOauth2 = async (\n flows: OAuthFlowsObjectSecret,\n type: keyof OAuthFlowsObjectSecret,\n selectedScopes: string[],\n /** We use the active server to set a base for relative redirect uris */\n activeServer: ServerObject | null,\n /** If we want to use the proxy */\n proxyUrl: string,\n /** Flattened environment variables used to resolve server URL templates like `{protocol}` */\n environmentVariables: Record<string, string> = {},\n): Promise<ErrorResponse<OAuth2Tokens>> => {\n const flow = flows[type]\n\n try {\n if (!flow) {\n return [new Error('Flow not found'), null]\n }\n\n const scopes = selectedScopes.join(' ')\n\n // Client Credentials or Password Flow\n if (type === 'clientCredentials' || type === 'password') {\n return authorizeServers(\n flows,\n type,\n scopes,\n {\n proxyUrl,\n },\n activeServer,\n environmentVariables,\n )\n }\n\n // Generate a random state string with the length of 8 characters\n const state = (Math.random() + 1).toString(36).substring(2, 10)\n\n const authorizationUrl = makeUrlAbsolute(\n flows[type]!['x-scalar-secret-auth-url'] ?? flows[type]!.authorizationUrl,\n getActiveServerBase(activeServer, environmentVariables),\n )\n\n const url = new URL(authorizationUrl)\n\n /** Special PKCE state */\n let pkce: PKCEState | null = null\n\n // Params unique to the flows\n if (type === 'implicit') {\n url.searchParams.set('response_type', 'token')\n } else if (type === 'authorizationCode') {\n const typedFlow = flows[type]! // Safe to assert due to earlier check\n\n url.searchParams.set('response_type', 'code')\n\n // PKCE\n if (typedFlow['x-usePkce'] !== 'no') {\n const codeVerifier = generateCodeVerifier()\n const codeChallenge = await generateCodeChallenge(codeVerifier, typedFlow['x-usePkce'])\n\n // Set state for later verification\n pkce = {\n codeVerifier,\n codeChallenge,\n codeChallengeMethod: typedFlow['x-usePkce'] === 'SHA-256' ? 'S256' : 'plain',\n }\n\n // Set the code challenge and method on the url\n url.searchParams.set('code_challenge', codeChallenge)\n url.searchParams.set('code_challenge_method', pkce.codeChallengeMethod)\n }\n }\n\n const typedFlow = flows[type]! // Safe to assert due to earlier check\n\n // Handle relative redirect uris\n if (typedFlow['x-scalar-secret-redirect-uri'].startsWith('/')) {\n const baseUrl =\n getServerUrl(activeServer, environmentVariables) || window.location.origin + window.location.pathname\n const redirectUri = new URL(typedFlow['x-scalar-secret-redirect-uri'], baseUrl).toString()\n\n url.searchParams.set('redirect_uri', redirectUri)\n } else {\n url.searchParams.set('redirect_uri', typedFlow['x-scalar-secret-redirect-uri'])\n }\n\n if (flow['x-scalar-security-query']) {\n Object.keys(flow['x-scalar-security-query']).forEach((key: string): void => {\n const value = flow['x-scalar-security-query']?.[key]\n if (!value) {\n return\n }\n url.searchParams.set(key, value)\n })\n }\n\n // Common to all flows\n url.searchParams.set('client_id', flow['x-scalar-secret-client-id'])\n url.searchParams.set('state', state)\n if (scopes) {\n url.searchParams.set('scope', scopes)\n }\n\n const windowFeatures = 'left=100,top=100,width=800,height=600'\n const authWindow = window.open(url, 'openAuth2Window', windowFeatures)\n\n // Open up a window and poll until closed or we have the data we want\n if (authWindow) {\n // We need to return a promise here due to the setInterval\n return new Promise<ErrorResponse<OAuth2Tokens>>((resolve) => {\n const checkWindowClosed = setInterval(() => {\n let accessToken: string | null = null\n let refreshToken: string | null = null\n let code: string | null = null\n let error: string | null = null\n let errorDescription: string | null = null\n\n try {\n const urlParams = new URL(authWindow.location.href).searchParams\n const tokenName = flow['x-tokenName'] || 'access_token'\n accessToken = urlParams.get(tokenName)\n refreshToken = urlParams.get('refresh_token')\n code = urlParams.get('code')\n\n error = urlParams.get('error')\n errorDescription = urlParams.get('error_description')\n\n // We may get the properties in a hash\n const hashParams = new URLSearchParams(authWindow.location.href.split('#')[1])\n accessToken ||= hashParams.get(tokenName)\n refreshToken ||= hashParams.get('refresh_token')\n code ||= hashParams.get('code')\n error ||= hashParams.get('error')\n errorDescription ||= hashParams.get('error_description')\n } catch (_e) {\n // Ignore CORS error from popup\n }\n\n // The window has closed OR we have what we are looking for so we stop polling\n if (authWindow.closed || accessToken || code || error) {\n clearInterval(checkWindowClosed)\n authWindow.close()\n\n if (error) {\n resolve([new Error(`OAuth error: ${error}${errorDescription ? ` (${errorDescription})` : ''}`), null])\n }\n\n // Implicit Flow\n else if (accessToken) {\n // State is a hash fragment and cannot be found through search params\n const _state = authWindow.location.href.match(/state=([^&]*)/)?.[1]\n\n if (_state === state) {\n resolve([null, { accessToken, ...(refreshToken ? { refreshToken } : {}) }])\n } else {\n resolve([new Error('State mismatch'), null])\n }\n }\n\n // Authorization Code Server Flow\n else if (code && type === 'authorizationCode') {\n const _state = new URL(authWindow.location.href).searchParams.get('state')\n\n if (_state === state) {\n // biome-ignore lint/nursery/noFloatingPromises: output of authorizeServers must be returned\n authorizeServers(\n flows,\n type,\n scopes,\n {\n code,\n pkce,\n proxyUrl,\n },\n activeServer,\n environmentVariables,\n ).then(resolve)\n } else {\n resolve([new Error('State mismatch'), null])\n }\n }\n // User closed window without authorizing\n else {\n clearInterval(checkWindowClosed)\n resolve([new Error('Window was closed without granting authorization'), null])\n }\n }\n }, 200)\n })\n }\n return [new Error('Failed to open auth window'), null]\n } catch (_) {\n return [new Error('Failed to authorize oauth2 flow'), null]\n }\n}\n\n/**\n * Makes the BE authorization call to grab the token server to server\n * Used for clientCredentials and authorizationCode\n */\nconst authorizeServers = async (\n flows: NonImplicitFlows,\n type: keyof NonImplicitFlows,\n scopes: string,\n {\n code,\n pkce,\n proxyUrl,\n }: {\n code?: string\n pkce?: PKCEState | null\n proxyUrl?: string\n } = {},\n activeServer: ServerObject | null,\n environmentVariables: Record<string, string> = {},\n): Promise<ErrorResponse<OAuth2Tokens>> => {\n const flow = flows[type]\n\n if (!flow) {\n return [new Error('OAuth2 flow was not defined'), null]\n }\n\n const formData = new URLSearchParams()\n\n // Only client credentials and password flows support scopes in the token request\n if (scopes && (type === 'clientCredentials' || type === 'password')) {\n formData.set('scope', scopes)\n }\n\n /** Where to add the credentials */\n const addCredentialsToBody = flow['x-scalar-credentials-location'] === 'body'\n const hasClientSecret = Boolean(flow['x-scalar-secret-client-secret'])\n /**\n * Public authorization-code clients still need client_id in the token body.\n * We only send it implicitly for that case to avoid conflicting with Basic auth.\n */\n const shouldSendClientIdInBody = addCredentialsToBody || (type === 'authorizationCode' && !hasClientSecret)\n\n if (shouldSendClientIdInBody) {\n formData.set('client_id', flow['x-scalar-secret-client-id'])\n }\n if (addCredentialsToBody && hasClientSecret) {\n formData.set('client_secret', flow['x-scalar-secret-client-secret'])\n }\n if ('x-scalar-secret-redirect-uri' in flow && flow['x-scalar-secret-redirect-uri']) {\n formData.set('redirect_uri', flow['x-scalar-secret-redirect-uri'])\n }\n\n // Authorization Code\n if (code) {\n formData.set('code', code)\n formData.set('grant_type', 'authorization_code')\n\n // PKCE\n if (pkce) {\n formData.set('code_verifier', pkce.codeVerifier)\n }\n }\n // Password\n else if (type === 'password') {\n const typedFlow = flows[type]! // Safe to assert due to earlier check\n formData.set('grant_type', 'password')\n formData.set('username', typedFlow['x-scalar-secret-username'])\n formData.set('password', typedFlow['x-scalar-secret-password'])\n }\n // Client Credentials\n else {\n formData.set('grant_type', 'client_credentials')\n }\n\n // Additional request body parameters\n if (flow['x-scalar-security-body']) {\n Object.entries(flow['x-scalar-security-body']).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n formData.set(key, String(value))\n }\n })\n }\n\n try {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/x-www-form-urlencoded',\n }\n\n // Add client id + secret to headers for confidential clients.\n if (!addCredentialsToBody && hasClientSecret) {\n headers.Authorization = `Basic ${encode(`${flow['x-scalar-secret-client-id']}:${flow['x-scalar-secret-client-secret']}`)}`\n }\n\n // Check if we should use the proxy\n const tokenUrl = makeUrlAbsolute(\n flow['x-scalar-secret-token-url'] ?? flow.tokenUrl,\n getActiveServerBase(activeServer, environmentVariables),\n )\n const url = shouldUseProxy(proxyUrl, tokenUrl)\n ? `${proxyUrl}?${new URLSearchParams([['scalar_url', tokenUrl]]).toString()}`\n : tokenUrl\n\n // Make the call\n const resp = await fetch(url, {\n method: 'POST',\n headers,\n body: formData,\n })\n const responseData = await resp.json()\n\n // Use custom token name if specified, otherwise default to access_token\n const tokenName = flow['x-tokenName'] || 'access_token'\n const accessToken = responseData[tokenName]\n const refreshToken = responseData.refresh_token\n\n return [null, { accessToken, ...(typeof refreshToken === 'string' ? { refreshToken } : {}) }]\n } catch {\n return [new Error('Failed to get an access token. Please check your credentials.'), null]\n }\n}\n"],"mappings":"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"}
{"version":3,"file":"oauth.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/oauth.ts"],"sourcesContent":["import type { ErrorResponse } from '@scalar/helpers/errors/normalize-error'\nimport { replaceEnvVariables, replacePathVariables } from '@scalar/helpers/regex/replace-variables'\nimport { isRelativePath } from '@scalar/helpers/url/is-relative-path'\nimport { makeUrlAbsolute } from '@scalar/helpers/url/make-url-absolute'\nimport { shouldUseProxy } from '@scalar/helpers/url/redirect-to-proxy'\nimport type { OAuthFlowsObjectSecret } from '@scalar/workspace-store/request-example'\nimport { getServerVariables } from '@scalar/workspace-store/request-example'\nimport type { ServerObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { encode, fromUint8Array } from 'js-base64'\n\n/** Oauth2 security schemes which are not implicit */\ntype NonImplicitFlows = Omit<OAuthFlowsObjectSecret, 'implicit'>\n\ntype PKCEState = {\n codeVerifier: string\n codeChallenge: string\n codeChallengeMethod: string\n}\n\nexport type OAuth2Tokens = {\n accessToken: string\n refreshToken?: string\n}\n\n/** Flow types that support token refresh (all except implicit) */\ntype RefreshableFlows = Exclude<keyof OAuthFlowsObjectSecret, 'implicit'>\n\nconst getServerUrl = (activeServer: ServerObject | null, environmentVariables: Record<string, string> = {}) => {\n return replaceEnvVariables(\n replacePathVariables(activeServer?.url ?? '', getServerVariables(activeServer)),\n environmentVariables,\n )\n}\n\nconst getActiveServerBase = (activeServer: ServerObject | null, environmentVariables: Record<string, string> = {}) => {\n const serverUrl = getServerUrl(activeServer, environmentVariables)\n\n if (!serverUrl) {\n return {}\n }\n\n if (isRelativePath(serverUrl)) {\n return typeof window === 'undefined' ? {} : { basePath: serverUrl }\n }\n\n return { baseUrl: serverUrl }\n}\n\n/**\n * Generates a random string for PKCE code verifier\n *\n * @see https://www.rfc-editor.org/rfc/rfc7636#page-8\n */\nconst generateCodeVerifier = (): string => {\n // Generate 32 random bytes\n const buffer = new Uint8Array(32)\n crypto.getRandomValues(buffer)\n\n // Base64URL encode the bytes\n return fromUint8Array(buffer, true)\n}\n\n/**\n * Creates a code challenge from the code verifier\n */\nconst generateCodeChallenge = async (verifier: string, encoding: 'SHA-256' | 'plain'): Promise<string> => {\n if (encoding === 'plain') {\n return verifier\n }\n\n // If crypto.subtle.digest is not a function, we cannot use SHA-256\n if (typeof crypto?.subtle?.digest !== 'function') {\n console.warn('SHA-256 is only supported when using https, using a plain text code challenge instead.')\n return verifier\n }\n\n // ASCII encoding is just taking the lower 8 bits of each character\n const encoder = new TextEncoder()\n const data = encoder.encode(verifier)\n const digest = await crypto.subtle.digest('SHA-256', data)\n\n // Base64URL encode the bytes\n return fromUint8Array(new Uint8Array(digest), true)\n}\n\n/**\n * Authorize oauth2 flow\n *\n * @returns the resolved oauth2 tokens\n */\nexport const authorizeOauth2 = async (\n flows: OAuthFlowsObjectSecret,\n type: keyof OAuthFlowsObjectSecret,\n selectedScopes: string[],\n /** We use the active server to set a base for relative redirect uris */\n activeServer: ServerObject | null,\n /** If we want to use the proxy */\n proxyUrl: string,\n /** Flattened environment variables used to resolve server URL templates like `{protocol}` */\n environmentVariables: Record<string, string> = {},\n): Promise<ErrorResponse<OAuth2Tokens>> => {\n const flow = flows[type]\n\n try {\n if (!flow) {\n return [new Error('Flow not found'), null]\n }\n\n const scopes = selectedScopes.join(' ')\n\n // Client Credentials or Password Flow\n if (type === 'clientCredentials' || type === 'password') {\n return authorizeServers(\n flows,\n type,\n scopes,\n {\n proxyUrl,\n },\n activeServer,\n environmentVariables,\n )\n }\n\n // Generate a random state string with the length of 8 characters\n const state = (Math.random() + 1).toString(36).substring(2, 10)\n\n const authorizationUrl = makeUrlAbsolute(\n flows[type]!['x-scalar-secret-auth-url'] ?? flows[type]!.authorizationUrl,\n getActiveServerBase(activeServer, environmentVariables),\n )\n\n const url = new URL(authorizationUrl)\n\n /** Special PKCE state */\n let pkce: PKCEState | null = null\n\n // Params unique to the flows\n if (type === 'implicit') {\n url.searchParams.set('response_type', 'token')\n } else if (type === 'authorizationCode') {\n const typedFlow = flows[type]! // Safe to assert due to earlier check\n\n url.searchParams.set('response_type', 'code')\n\n // PKCE\n if (typedFlow['x-usePkce'] !== 'no') {\n const codeVerifier = generateCodeVerifier()\n const codeChallenge = await generateCodeChallenge(codeVerifier, typedFlow['x-usePkce'])\n\n // Set state for later verification\n pkce = {\n codeVerifier,\n codeChallenge,\n codeChallengeMethod: typedFlow['x-usePkce'] === 'SHA-256' ? 'S256' : 'plain',\n }\n\n // Set the code challenge and method on the url\n url.searchParams.set('code_challenge', codeChallenge)\n url.searchParams.set('code_challenge_method', pkce.codeChallengeMethod)\n }\n }\n\n const typedFlow = flows[type]! // Safe to assert due to earlier check\n\n // Handle relative redirect uris\n if (typedFlow['x-scalar-secret-redirect-uri'].startsWith('/')) {\n const baseUrl =\n getServerUrl(activeServer, environmentVariables) || window.location.origin + window.location.pathname\n const redirectUri = new URL(typedFlow['x-scalar-secret-redirect-uri'], baseUrl).toString()\n\n url.searchParams.set('redirect_uri', redirectUri)\n } else {\n url.searchParams.set('redirect_uri', typedFlow['x-scalar-secret-redirect-uri'])\n }\n\n if (flow['x-scalar-security-query']) {\n Object.keys(flow['x-scalar-security-query']).forEach((key: string): void => {\n const value = flow['x-scalar-security-query']?.[key]\n if (!value) {\n return\n }\n url.searchParams.set(key, value)\n })\n }\n\n // Common to all flows\n url.searchParams.set('client_id', flow['x-scalar-secret-client-id'])\n url.searchParams.set('state', state)\n if (scopes) {\n url.searchParams.set('scope', scopes)\n }\n\n const windowFeatures = 'left=100,top=100,width=800,height=600'\n const authWindow = window.open(url, 'openAuth2Window', windowFeatures)\n\n // Open up a window and poll until closed or we have the data we want\n if (authWindow) {\n // We need to return a promise here due to the setInterval\n return new Promise<ErrorResponse<OAuth2Tokens>>((resolve) => {\n const checkWindowClosed = setInterval(() => {\n let accessToken: string | null = null\n let refreshToken: string | null = null\n let code: string | null = null\n let error: string | null = null\n let errorDescription: string | null = null\n\n try {\n const urlParams = new URL(authWindow.location.href).searchParams\n const tokenName = flow['x-tokenName'] || 'access_token'\n accessToken = urlParams.get(tokenName)\n refreshToken = urlParams.get('refresh_token')\n code = urlParams.get('code')\n\n error = urlParams.get('error')\n errorDescription = urlParams.get('error_description')\n\n // We may get the properties in a hash\n const hashParams = new URLSearchParams(authWindow.location.href.split('#')[1])\n accessToken ||= hashParams.get(tokenName)\n refreshToken ||= hashParams.get('refresh_token')\n code ||= hashParams.get('code')\n error ||= hashParams.get('error')\n errorDescription ||= hashParams.get('error_description')\n } catch (_e) {\n // Ignore CORS error from popup\n }\n\n // The window has closed OR we have what we are looking for so we stop polling\n if (authWindow.closed || accessToken || code || error) {\n clearInterval(checkWindowClosed)\n authWindow.close()\n\n if (error) {\n resolve([new Error(`OAuth error: ${error}${errorDescription ? ` (${errorDescription})` : ''}`), null])\n }\n\n // Implicit Flow\n else if (accessToken) {\n // State is a hash fragment and cannot be found through search params\n const _state = authWindow.location.href.match(/state=([^&]*)/)?.[1]\n\n if (_state === state) {\n resolve([null, { accessToken, ...(refreshToken ? { refreshToken } : {}) }])\n } else {\n resolve([new Error('State mismatch'), null])\n }\n }\n\n // Authorization Code Server Flow\n else if (code && type === 'authorizationCode') {\n const _state = new URL(authWindow.location.href).searchParams.get('state')\n\n if (_state === state) {\n // biome-ignore lint/nursery/noFloatingPromises: output of authorizeServers must be returned\n authorizeServers(\n flows,\n type,\n scopes,\n {\n code,\n pkce,\n proxyUrl,\n },\n activeServer,\n environmentVariables,\n ).then(resolve)\n } else {\n resolve([new Error('State mismatch'), null])\n }\n }\n // User closed window without authorizing\n else {\n clearInterval(checkWindowClosed)\n resolve([new Error('Window was closed without granting authorization'), null])\n }\n }\n }, 200)\n })\n }\n return [new Error('Failed to open auth window'), null]\n } catch (_) {\n return [new Error('Failed to authorize oauth2 flow'), null]\n }\n}\n\n/**\n * Makes the BE authorization call to grab the token server to server\n * Used for clientCredentials and authorizationCode\n */\nconst authorizeServers = async (\n flows: NonImplicitFlows,\n type: keyof NonImplicitFlows,\n scopes: string,\n {\n code,\n pkce,\n proxyUrl,\n }: {\n code?: string\n pkce?: PKCEState | null\n proxyUrl?: string\n } = {},\n activeServer: ServerObject | null,\n environmentVariables: Record<string, string> = {},\n): Promise<ErrorResponse<OAuth2Tokens>> => {\n const flow = flows[type]\n\n if (!flow) {\n return [new Error('OAuth2 flow was not defined'), null]\n }\n\n const formData = new URLSearchParams()\n\n // Only client credentials and password flows support scopes in the token request\n if (scopes && (type === 'clientCredentials' || type === 'password')) {\n formData.set('scope', scopes)\n }\n\n /** Where to add the credentials */\n const addCredentialsToBody = flow['x-scalar-credentials-location'] === 'body'\n const hasClientSecret = Boolean(flow['x-scalar-secret-client-secret'])\n /**\n * Public authorization-code clients still need client_id in the token body.\n * We only send it implicitly for that case to avoid conflicting with Basic auth.\n */\n const shouldSendClientIdInBody = addCredentialsToBody || (type === 'authorizationCode' && !hasClientSecret)\n\n if (shouldSendClientIdInBody) {\n formData.set('client_id', flow['x-scalar-secret-client-id'])\n }\n if (addCredentialsToBody && hasClientSecret) {\n formData.set('client_secret', flow['x-scalar-secret-client-secret'])\n }\n if ('x-scalar-secret-redirect-uri' in flow && flow['x-scalar-secret-redirect-uri']) {\n formData.set('redirect_uri', flow['x-scalar-secret-redirect-uri'])\n }\n\n // Authorization Code\n if (code) {\n formData.set('code', code)\n formData.set('grant_type', 'authorization_code')\n\n // PKCE\n if (pkce) {\n formData.set('code_verifier', pkce.codeVerifier)\n }\n }\n // Password\n else if (type === 'password') {\n const typedFlow = flows[type]! // Safe to assert due to earlier check\n formData.set('grant_type', 'password')\n formData.set('username', typedFlow['x-scalar-secret-username'])\n formData.set('password', typedFlow['x-scalar-secret-password'])\n }\n // Client Credentials\n else {\n formData.set('grant_type', 'client_credentials')\n }\n\n // Additional request body parameters\n if (flow['x-scalar-security-body']) {\n Object.entries(flow['x-scalar-security-body']).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n formData.set(key, String(value))\n }\n })\n }\n\n try {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/x-www-form-urlencoded',\n }\n\n // Add client id + secret to headers for confidential clients.\n if (!addCredentialsToBody && hasClientSecret) {\n headers.Authorization = `Basic ${encode(`${flow['x-scalar-secret-client-id']}:${flow['x-scalar-secret-client-secret']}`)}`\n }\n\n // Check if we should use the proxy\n const tokenUrl = makeUrlAbsolute(\n flow['x-scalar-secret-token-url'] ?? flow.tokenUrl,\n getActiveServerBase(activeServer, environmentVariables),\n )\n const url = shouldUseProxy(proxyUrl, tokenUrl)\n ? `${proxyUrl}?${new URLSearchParams([['scalar_url', tokenUrl]]).toString()}`\n : tokenUrl\n\n // Make the call\n const resp = await fetch(url, {\n method: 'POST',\n headers,\n body: formData,\n })\n const responseData = await resp.json()\n\n // Use custom token name if specified, otherwise default to access_token\n const tokenName = flow['x-tokenName'] || 'access_token'\n const accessToken = responseData[tokenName]\n const refreshToken = responseData.refresh_token\n\n return [null, { accessToken, ...(typeof refreshToken === 'string' ? { refreshToken } : {}) }]\n } catch {\n return [new Error('Failed to get an access token. Please check your credentials.'), null]\n }\n}\n\n/**\n * Exchange a refresh token for a new access token using the `grant_type=refresh_token` flow.\n *\n * Uses the stored refresh token, client credentials, and the token URL (or refreshUrl when available)\n * to request fresh tokens from the authorization server per RFC 6749 Section 6.\n */\nexport const refreshOauth2Token = async (\n flows: OAuthFlowsObjectSecret,\n type: RefreshableFlows,\n /** If we want to use the proxy */\n proxyUrl: string,\n /** We use the active server to set a base for relative URLs */\n activeServer: ServerObject | null,\n /** Flattened environment variables used to resolve server URL templates */\n environmentVariables: Record<string, string> = {},\n): Promise<ErrorResponse<OAuth2Tokens>> => {\n const flow = flows[type]\n\n if (!flow) {\n return [new Error('OAuth2 flow was not defined'), null]\n }\n\n const refreshToken = flow['x-scalar-secret-refresh-token']\n if (!refreshToken) {\n return [new Error('No refresh token available'), null]\n }\n\n const formData = new URLSearchParams()\n formData.set('grant_type', 'refresh_token')\n formData.set('refresh_token', refreshToken)\n\n const addCredentialsToBody = flow['x-scalar-credentials-location'] === 'body'\n const hasClientSecret = Boolean(flow['x-scalar-secret-client-secret'])\n /**\n * Public authorization-code clients still need client_id in the refresh body per RFC 6749 Section 6.\n * We only send it implicitly for that case to avoid conflicting with Basic auth.\n */\n const shouldSendClientIdInBody = addCredentialsToBody || (type === 'authorizationCode' && !hasClientSecret)\n\n if (shouldSendClientIdInBody) {\n formData.set('client_id', flow['x-scalar-secret-client-id'])\n }\n if (addCredentialsToBody && hasClientSecret) {\n formData.set('client_secret', flow['x-scalar-secret-client-secret'])\n }\n\n if (flow['x-scalar-security-body']) {\n Object.entries(flow['x-scalar-security-body']).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n formData.set(key, String(value))\n }\n })\n }\n\n try {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/x-www-form-urlencoded',\n }\n\n if (!addCredentialsToBody && hasClientSecret) {\n headers.Authorization = `Basic ${encode(`${flow['x-scalar-secret-client-id']}:${flow['x-scalar-secret-client-secret']}`)}`\n }\n\n const refreshUrl = flow.refreshUrl || flow['x-scalar-secret-token-url'] || flow.tokenUrl\n const absoluteRefreshUrl = makeUrlAbsolute(refreshUrl, getActiveServerBase(activeServer, environmentVariables))\n const url = shouldUseProxy(proxyUrl, absoluteRefreshUrl)\n ? `${proxyUrl}?${new URLSearchParams([['scalar_url', absoluteRefreshUrl]]).toString()}`\n : absoluteRefreshUrl\n\n const resp = await fetch(url, {\n method: 'POST',\n headers,\n body: formData,\n })\n const responseData = await resp.json()\n\n const tokenName = flow['x-tokenName'] || 'access_token'\n const accessToken = responseData[tokenName]\n const newRefreshToken = responseData.refresh_token\n\n if (!accessToken) {\n return [new Error(responseData.error_description ?? responseData.error ?? 'Token refresh failed'), null]\n }\n\n return [\n null,\n {\n accessToken,\n ...(typeof newRefreshToken === 'string' ? { refreshToken: newRefreshToken } : { refreshToken }),\n },\n ]\n } catch {\n return [new Error('Failed to refresh the access token. Please re-authorize.'), null]\n }\n}\n"],"mappings":"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"}

@@ -79,2 +79,4 @@ import { type CodeMirrorLanguage, type Extension } from '@scalar/use-codemirror';

withVariables?: boolean;
/** Enable fake data suggestions like $guid, $timestamp, etc. Should only be enabled for parameters and request bodies */
withFakeData?: boolean;
/** Emit change event even if the value is the same */

@@ -107,5 +109,5 @@ alwaysEmitChange?: boolean;

}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
blur: (value: string, event: FocusEvent) => any;
submit: (value: string, event: FocusEvent | KeyboardEvent) => any;
"update:modelValue": (value: string) => any;
blur: (value: string, event: FocusEvent) => any;
navigate: (route: {

@@ -161,2 +163,4 @@ page: "document";

withVariables?: boolean;
/** Enable fake data suggestions like $guid, $timestamp, etc. Should only be enabled for parameters and request bodies */
withFakeData?: boolean;
/** Emit change event even if the value is the same */

@@ -171,5 +175,5 @@ alwaysEmitChange?: boolean;

}> & Readonly<{
onBlur?: ((value: string, event: FocusEvent) => any) | undefined;
onSubmit?: ((value: string, event: FocusEvent | KeyboardEvent) => any) | undefined;
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
onBlur?: ((value: string, event: FocusEvent) => any) | undefined;
onNavigate?: ((route: {

@@ -176,0 +180,0 @@ page: "document";

@@ -1,1 +0,1 @@

{"version":3,"file":"CodeInput.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/components/code-input/CodeInput.vue"],"names":[],"mappings":"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"}
{"version":3,"file":"CodeInput.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/components/code-input/CodeInput.vue"],"names":[],"mappings":"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"}

@@ -6,3 +6,3 @@ import _plugin_vue_export_helper_default from "../../../_virtual/_plugin-vue_export-helper.js";

//#region src/v2/components/code-input/CodeInput.vue
var CodeInput_default = /* @__PURE__ */ _plugin_vue_export_helper_default(CodeInput_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-167b1bd5"]]);
var CodeInput_default = /* @__PURE__ */ _plugin_vue_export_helper_default(CodeInput_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-6499ec1f"]]);
//#endregion

@@ -9,0 +9,0 @@ export { CodeInput_default as default };

@@ -1,1 +0,1 @@

{"version":3,"file":"CodeInput.vue.js","names":[],"sources":["../../../../src/v2/components/code-input/CodeInput.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type CodeInputModelValue =\n | string\n | number\n | boolean\n | Array<string | number | boolean>\n | Record<string, unknown>\n\n/**\n * CodeInput\n *\n * A versatile input component that adapts its rendering based on props:\n * - Disabled mode: Read-only text display\n * - Select mode: Dropdown for enums, booleans, or examples\n * - Editor mode: CodeMirror with environment variable support\n *\n * Type `{{` to trigger autocomplete for environment variables and runtime context functions\n * (for example `{{$guid}}`) when an environment is provided.\n * It takes in any data but always will emit a string value,\n * this string should then be parsed in accordance to the schema or content type.\n *\n * @example\n * ```vue\n * <!-- Basic input with environment variables -->\n * <CodeInput v-model=\"value\" :environment=\"env\" />\n *\n * <!-- Boolean select -->\n * <CodeInput v-model=\"flag\" type=\"boolean\" />\n *\n * <!-- JSON editor with linting -->\n * <CodeInput v-model=\"data\" language=\"json\" :lint=\"true\" />\n * ```\n */\nexport default {\n inheritAttrs: false,\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { isDefined } from '@scalar/helpers/array/is-defined'\nimport {\n colorPicker as colorPickerExtension,\n useCodeMirror,\n useDropdown,\n type CodeMirrorLanguage,\n type Extension,\n} from '@scalar/use-codemirror'\nimport {\n CONTEXT_FUNCTION_NAMES,\n getContextFunctionComment,\n isContextFunctionName,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { nanoid } from 'nanoid'\nimport { computed, ref, toRef, useAttrs, watch, type Ref } from 'vue'\n\nimport DataTableInputSelect from '@/v2/components/data-table/DataTableInputSelect.vue'\nimport EnvironmentVariableDropdown from '@/v2/features/environments/components/EnvironmentVariablesDropdown.vue'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nimport { backspaceCommand, pillPlugin } from './code-variable-widget'\n\ntype Props = {\n modelValue: CodeInputModelValue\n /** Environment for variable substitution. Pass undefined to disable environment variables */\n environment: XScalarEnvironment | undefined\n /** Type of the input value, affects rendering mode for booleans */\n type?: string | string[]\n /** Render as disabled text display */\n disabled?: boolean\n /** Show error styling */\n error?: boolean\n /** Layout context affects styling and behavior */\n layout?: ClientLayout\n /** Predefined enum values, triggers select mode */\n enum?: string[]\n /** Example values, triggers select mode */\n examples?: string[]\n /** Default value to show in select mode */\n default?: Props['modelValue']\n /** Allow null in boolean select options */\n nullable?: boolean\n /** Placeholder text for empty input */\n placeholder?: string\n /** Show required indicator */\n required?: boolean\n /** Enable color picker extension */\n colorPicker?: boolean\n /** Show line numbers in editor */\n lineNumbers?: boolean\n /** Enable linting */\n lint?: boolean\n /** Enable line wrapping */\n lineWrapping?: boolean\n /** CodeMirror language mode */\n language?: CodeMirrorLanguage\n /** Additional CodeMirror extensions */\n extensions?: Extension[]\n /** Disable tab key for indentation */\n disableTabIndent?: boolean\n /** Disable enter key */\n disableEnter?: boolean\n /** Disable automatic bracket closing */\n disableCloseBrackets?: boolean\n /** Emit submit event on blur */\n emitOnBlur?: boolean\n /** Enable environment variable pills */\n withVariables?: boolean\n /** Emit change event even if the value is the same */\n alwaysEmitChange?: boolean\n /** Custom change handler, prevents default emit */\n handleFieldChange?: (value: string) => void\n /** Custom submit handler, prevents default emit */\n handleFieldSubmit?: (value: string) => void\n /** Put a linethrough on the input text */\n linethrough?: boolean\n}\n\nconst {\n modelValue,\n environment,\n type,\n disabled = false,\n error = false,\n layout = 'desktop',\n enum: enumProp,\n examples,\n default: defaultProp,\n nullable = false,\n placeholder,\n required,\n colorPicker = false,\n lineNumbers = false,\n lint = false,\n lineWrapping = false,\n language,\n extensions = [],\n disableTabIndent = false,\n disableEnter = false,\n disableCloseBrackets = false,\n emitOnBlur = true,\n alwaysEmitChange = false,\n withVariables = true,\n handleFieldChange,\n handleFieldSubmit,\n} = defineProps<Props>()\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string]\n 'submit': [value: string, event: KeyboardEvent | FocusEvent]\n 'navigate': [route: { page: 'document'; path: 'environment' }]\n 'blur': [value: string, event: FocusEvent]\n}>()\n\n// ---------------------------------------------------------------------------\n// Component identity and focus state\n\nconst attrs = useAttrs() as { id?: string }\nconst componentId = attrs.id || `id-${nanoid()}`\nconst isFocused = ref(false)\n\n// ---------------------------------------------------------------------------\n// Rendering mode detection\n\n/**\n * Determines if we should render a select dropdown for boolean types.\n */\nconst isBooleanMode = computed((): boolean => {\n if (enumProp?.length) {\n return false\n }\n return type === 'boolean' || (Array.isArray(type) && type.includes('boolean'))\n})\n\n/**\n * Options for boolean select mode.\n */\nconst booleanOptions = computed((): string[] =>\n nullable ? ['true', 'false', 'null'] : ['true', 'false'],\n)\n\n/**\n * Default type when dealing with type arrays.\n * Finds the first non-null type.\n */\nconst defaultType = computed((): string | undefined => {\n if (Array.isArray(type)) {\n return type.find((t) => t !== 'null') ?? 'string'\n }\n return type\n})\n\n// ---------------------------------------------------------------------------\n// Event handlers\n\n/**\n * Handles value changes during typing.\n */\nconst handleChange = (value: string): void => {\n if (!alwaysEmitChange && value === serializeValue(modelValue)) {\n return\n }\n\n // Use custom handler or emit update\n if (handleFieldChange) {\n handleFieldChange(value)\n } else {\n emit('update:modelValue', value)\n }\n}\n\n/**\n * Handles form submission (enter key or blur with emitOnBlur).\n */\nconst handleSubmit = (\n value: string,\n event: KeyboardEvent | FocusEvent,\n): void => {\n if (handleFieldSubmit) {\n handleFieldSubmit(value)\n } else {\n emit('submit', value, event)\n }\n}\n\n/**\n * Handles input blur event.\n */\nconst handleBlur = (value: string, event: FocusEvent): void => {\n isFocused.value = false\n\n if (emitOnBlur && modelValue) {\n handleSubmit(value, event)\n }\n\n emit('blur', value, event)\n}\n\n/**\n * Handles model value updates from select components.\n */\nconst handleSelectChange = (value: string): void =>\n emit('update:modelValue', value)\n\n// ---------------------------------------------------------------------------\n// CodeMirror setup\n\n/**\n * Build extensions array.\n * Note: Extensions are not reactive after initialization.\n */\nconst buildExtensions = (): Extension[] => {\n const extensionsList: Extension[] = [...extensions]\n\n if (colorPicker) {\n extensionsList.push(colorPickerExtension)\n }\n\n return extensionsList\n}\n\n/**\n * Reactive pill plugin for environment variable visualization.\n */\nconst contextFunctionDropdownItems = computed(() =>\n CONTEXT_FUNCTION_NAMES.map((key) => ({\n key,\n description: getContextFunctionComment(key),\n })),\n)\n\nconst pillPluginExtension = computed(() =>\n pillPlugin({\n environment,\n isContextFunctionName,\n isReadOnly: layout === 'modal',\n }),\n)\n\n/**\n * Combined extensions for CodeMirror.\n */\nconst codeMirrorExtensions = computed((): Extension[] => [\n ...buildExtensions(),\n pillPluginExtension.value,\n backspaceCommand,\n])\n\nconst codeMirrorRef: Ref<HTMLDivElement | null> = ref(null)\n\n/** Converts the model value to a string for CodeMirror */\nconst serializeValue = (value: CodeInputModelValue): string => {\n if (typeof value === 'string') {\n return value\n }\n return JSON.stringify(value)\n}\n\nconst { codeMirror, setCodeMirrorContent } = useCodeMirror({\n content: toRef(() => serializeValue(modelValue)),\n onChange: (value) => {\n handleChange(value)\n updateDropdownVisibility()\n },\n onFocus: () => {\n isFocused.value = true\n },\n onBlur: handleBlur,\n codeMirrorRef,\n disableTabIndent: toRef(() => disableTabIndent),\n disableEnter: toRef(() => disableEnter),\n disableCloseBrackets: toRef(() => disableCloseBrackets),\n lineNumbers: toRef(() => lineNumbers),\n language: toRef(() => language),\n lint: toRef(() => lint),\n extensions: codeMirrorExtensions,\n placeholder: toRef(() => placeholder),\n})\n\n/**\n * Handle autofocus attribute.\n */\nwatch(codeMirror, () => {\n if (codeMirror.value && Object.hasOwn(attrs, 'autofocus')) {\n codeMirror.value.focus()\n }\n})\n\n// ---------------------------------------------------------------------------\n// Environment variable dropdown\n\nconst showDropdown = ref(false)\nconst dropdownQuery = ref('')\nconst dropdownPosition = ref({ left: 0, top: 0 })\nconst dropdownRef = ref<InstanceType<\n typeof EnvironmentVariableDropdown\n> | null>(null)\n\nconst { handleDropdownSelect, updateDropdownVisibility } = useDropdown({\n codeMirror,\n query: dropdownQuery,\n showDropdown,\n dropdownPosition,\n})\n\n/**\n * Determines if the environment variable dropdown should be visible.\n */\nconst displayVariablesDropdown = computed((): boolean => {\n return (\n showDropdown.value &&\n withVariables &&\n layout !== 'modal' &&\n Boolean(environment)\n )\n})\n\n// ---------------------------------------------------------------------------\n// Keyboard event handling\n\n/**\n * Handles keyboard navigation for dropdown and form submission.\n */\nconst handleKeyDown = (key: string, event: KeyboardEvent): void => {\n if (showDropdown.value) {\n if (key === 'down' || key === 'up') {\n event.preventDefault()\n dropdownRef.value?.handleArrowKey(key)\n } else if (key === 'enter') {\n event.preventDefault()\n dropdownRef.value?.handleSelect()\n }\n return\n }\n\n if (key === 'escape' && !disableTabIndent) {\n event.stopPropagation()\n }\n\n if (key === 'enter' && event.target instanceof HTMLDivElement) {\n handleSubmit(event.target.textContent ?? '', event)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n\ndefineExpose({\n /**\n * Focus the codemirror element\n *\n * @param cursorAtEnd boolean place the cursor at the end of the input\n */\n focus: (position?: 'start' | 'end' | number) => {\n if (!codeMirror.value) {\n return\n }\n codeMirror.value.focus()\n\n if (!isDefined(position)) {\n return\n }\n\n const anchor = (() => {\n if (position === 'start') {\n return 0\n }\n if (position === 'end') {\n return codeMirror.value.state.doc.length\n }\n return position\n })()\n\n // Move the cursor to the specified position\n codeMirror.value.dispatch({\n selection: { anchor },\n scrollIntoView: true,\n })\n },\n isFocused,\n handleChange,\n handleSubmit,\n handleBlur,\n booleanOptions,\n codeMirror,\n codeMirrorRef,\n modelValue,\n setCodeMirrorContent,\n cursorPosition: () => codeMirror.value?.state.selection.main.head,\n serializeValue,\n})\n</script>\n\n<template>\n <!-- Disabled mode: read-only text display -->\n <div\n v-if=\"disabled\"\n class=\"text-c-2 flex cursor-default items-center justify-center\"\n :class=\"{\n 'font-code pr-2 pl-1 text-base': layout === 'modal',\n 'px-2': layout !== 'modal',\n 'line-through': linethrough,\n }\"\n data-testid=\"code-input-disabled\">\n <span class=\"whitespace-nowrap\">{{ modelValue }}</span>\n </div>\n\n <!-- Enum mode: select dropdown with predefined values -->\n <DataTableInputSelect\n v-else-if=\"enumProp?.length\"\n :default=\"defaultProp\"\n :modelValue=\"modelValue\"\n :type=\"defaultType\"\n :value=\"enumProp\"\n @update:modelValue=\"handleSelectChange\" />\n\n <!-- Boolean mode: select dropdown with true/false (and optionally null) -->\n <DataTableInputSelect\n v-else-if=\"isBooleanMode\"\n :default=\"defaultProp\"\n :modelValue=\"modelValue\"\n :value=\"booleanOptions\"\n @update:modelValue=\"handleSelectChange\" />\n\n <!-- Examples mode: select dropdown with example values -->\n <DataTableInputSelect\n v-else-if=\"examples?.length\"\n :default=\"defaultProp\"\n :modelValue=\"modelValue\"\n :value=\"examples\"\n @update:modelValue=\"handleSelectChange\" />\n\n <!-- Editor mode: CodeMirror with environment variable support -->\n <div\n v-else\n :id=\"componentId\"\n v-bind=\"$attrs\"\n ref=\"codeMirrorRef\"\n class=\"group/input group-[.alert]:outline-orange group-[.error]:outline-red font-code peer relative w-full overflow-hidden text-xs leading-[1.44] whitespace-nowrap -outline-offset-1 has-[:focus-visible]:rounded-[4px] has-[:focus-visible]:outline\"\n :class=\"{\n 'line-wrapping has-[:focus-visible]:bg-b-1 has-[:focus-visible]:absolute has-[:focus-visible]:z-1':\n lineWrapping,\n 'flow-code-input--error': error,\n 'line-through': linethrough,\n }\"\n @keydown.down.stop=\"handleKeyDown('down', $event)\"\n @keydown.enter=\"handleKeyDown('enter', $event)\"\n @keydown.escape=\"handleKeyDown('escape', $event)\"\n @keydown.up.stop=\"handleKeyDown('up', $event)\">\n <!-- Tab exit hint (shown when focused) -->\n <div\n v-if=\"!disableTabIndent\"\n class=\"z-context text-c-2 absolute right-1.5 bottom-1 hidden font-sans group-has-[:focus-visible]/input:block\"\n role=\"alert\">\n Press\n <kbd class=\"-mx-0.25 rounded border px-0.5 font-mono\">Esc</kbd> then\n <kbd class=\"-mx-0.25 rounded border px-0.5 font-mono\">Tab</kbd> to exit\n </div>\n </div>\n\n <!-- Warning slot (positioned absolutely) -->\n <div\n v-if=\"$slots.warning\"\n class=\"centered-y text-orange absolute right-7 text-xs\">\n <slot name=\"warning\" />\n </div>\n\n <!-- Icon slot (positioned absolutely) -->\n <div\n v-if=\"$slots.icon\"\n class=\"centered-y absolute right-0 flex h-full items-center p-1.5 group-has-[.cm-focused]:z-1\">\n <slot name=\"icon\" />\n </div>\n\n <!-- Required indicator -->\n <div\n v-if=\"required\"\n class=\"required centered-y text-xxs text-c-3 group-[.error]:text-red bg-b-1 pointer-events-none absolute right-0 mr-0.5 pt-px pr-2 opacity-100 shadow-[-8px_0_4px_var(--scalar-background-1)] transition-opacity duration-150 group-[.alert]:bg-transparent group-[.alert]:shadow-none group-[.error]:bg-transparent group-[.error]:shadow-none peer-has-[.cm-focused]:opacity-0\">\n Required\n </div>\n\n <!-- Environment variable autocomplete dropdown -->\n <EnvironmentVariableDropdown\n v-if=\"displayVariablesDropdown && environment\"\n ref=\"dropdownRef\"\n :contextFunctionItems=\"contextFunctionDropdownItems\"\n :dropdownPosition=\"dropdownPosition\"\n :environment=\"environment\"\n :query=\"dropdownQuery\"\n @redirect=\"emit('navigate', { page: 'document', path: 'environment' })\"\n @select=\"handleDropdownSelect\" />\n</template>\n<style scoped>\n/*\n Deep styling for customizing Codemirror\n */\n:deep(.cm-editor) {\n height: 100%;\n outline: none;\n padding: 0;\n background: transparent;\n}\n:deep(.cm-placeholder) {\n color: var(--scalar-color-3);\n}\n:deep(.cm-content) {\n font-family: var(--scalar-font-code);\n font-size: var(--scalar-small);\n max-height: 20px;\n padding: 8px 0;\n}\n/* Tooltip helper */\n:deep(.cm-tooltip) {\n background: transparent !important;\n filter: brightness(var(--scalar-lifted-brightness));\n border-radius: var(--scalar-radius);\n box-shadow: var(--scalar-shadow-2);\n border: none !important;\n outline: none !important;\n overflow: hidden !important;\n}\n:deep(.cm-tooltip-autocomplete ul li) {\n padding: 3px 6px !important;\n}\n:deep(.cm-completionIcon-type:after) {\n color: var(--scalar-color-3) !important;\n}\n:deep(.cm-tooltip-autocomplete ul li[aria-selected]) {\n background: var(--scalar-background-2) !important;\n color: var(--scalar-color-1) !important;\n}\n:deep(.cm-tooltip-autocomplete ul) {\n padding: 6px !important;\n position: relative;\n}\n:deep(.cm-tooltip-autocomplete ul li:hover) {\n border-radius: 3px;\n color: var(--scalar-color-1) !important;\n background: var(--scalar-background-3) !important;\n}\n/* Disable active line highlighting */\n:deep(.cm-activeLine),\n:deep(.cm-activeLineGutter) {\n background-color: transparent;\n}\n/* Color selection matching */\n:deep(.cm-selectionMatch),\n:deep(.cm-matchingBracket) {\n border-radius: var(--scalar-radius);\n background: var(--scalar-background-4) !important;\n}\n/* Color Picker Swatches */\n:deep(.cm-css-color-picker-wrapper) {\n display: inline-flex;\n outline: 1px solid var(--scalar-background-3);\n border-radius: 3px;\n overflow: hidden;\n}\n/* Number gutter */\n:deep(.cm-gutters) {\n background-color: transparent;\n border-right: none;\n color: var(--scalar-color-3);\n font-size: var(--scalar-small);\n line-height: 22px;\n border-radius: 0 0 0 3px;\n}\n:deep(.cm-gutters:before) {\n content: '';\n position: absolute;\n top: 2px;\n left: 2px;\n width: calc(100% - 2px);\n height: calc(100% - 4px);\n border-radius: var(--scalar-radius) 0 0 var(--scalar-radius);\n background-color: var(--scalar-background-1);\n}\n:deep(.cm-gutterElement) {\n font-family: var(--scalar-font-code) !important;\n padding-left: 0px !important;\n padding-right: 6px !important;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n position: relative;\n}\n:deep(.cm-lineNumbers .cm-gutterElement) {\n min-width: fit-content;\n}\n:deep(.cm-gutter + .cm-gutter :not(.cm-foldGutter) .cm-gutterElement) {\n padding-left: 0 !important;\n}\n:deep(.cm-scroller) {\n overflow: auto;\n}\n.line-wrapping:focus-within :deep(.cm-content) {\n display: inline-table;\n min-height: fit-content;\n padding: 3px 6px;\n white-space: break-spaces;\n word-break: break-all;\n}\n</style>\n<style>\n.cm-pill {\n color: var(--scalar-color-1) !important;\n padding: 0px 9px;\n border-radius: 3px;\n display: inline-block;\n border-radius: 30px;\n font-size: var(--scalar-small);\n}\n.light-mode .cm-pill {\n background: var(--scalar-background-3) !important;\n}\n.dark-mode .cm-pill {\n background: color-mix(in srgb, var(--tw-bg-base), transparent 90%) !important;\n}\n.cm-pill--context-fn {\n border: 1px dashed color-mix(in srgb, var(--scalar-color-3), transparent 35%);\n padding: 0px 8px;\n}\n.light-mode .cm-pill--context-fn {\n background: color-mix(\n in srgb,\n var(--scalar-background-3),\n transparent 40%\n ) !important;\n}\n.dark-mode .cm-pill--context-fn {\n background: color-mix(\n in srgb,\n var(--scalar-background-3),\n transparent 55%\n ) !important;\n}\n.cm-pill:first-of-type {\n margin-left: 0;\n}\n.cm-editor .cm-widgetBuffer {\n display: none;\n}\n.cm-foldPlaceholder:hover {\n color: var(--scalar-color-1);\n}\n.cm-foldGutter .cm-gutterElement {\n font-size: var(--scalar-heading-4);\n padding: 2px !important;\n}\n.cm-foldGutter .cm-gutterElement:first-of-type {\n display: none;\n}\n.cm-foldGutter .cm-gutterElement .cm-foldMarker {\n padding: 2px;\n padding-top: 2px;\n}\n.cm-foldGutter .cm-gutterElement:hover .cm-foldMarker {\n background: var(--scalar-background-2);\n border-radius: var(--scalar-radius);\n color: var(--scalar-color-1);\n}\n</style>\n"],"mappings":""}
{"version":3,"file":"CodeInput.vue.js","names":[],"sources":["../../../../src/v2/components/code-input/CodeInput.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type CodeInputModelValue =\n | string\n | number\n | boolean\n | Array<string | number | boolean>\n | Record<string, unknown>\n\n/**\n * CodeInput\n *\n * A versatile input component that adapts its rendering based on props:\n * - Disabled mode: Read-only text display\n * - Select mode: Dropdown for enums, booleans, or examples\n * - Editor mode: CodeMirror with environment variable support\n *\n * Type `{{` to trigger autocomplete for environment variables and runtime context functions\n * (for example `{{$guid}}`) when an environment is provided.\n * It takes in any data but always will emit a string value,\n * this string should then be parsed in accordance to the schema or content type.\n *\n * @example\n * ```vue\n * <!-- Basic input with environment variables -->\n * <CodeInput v-model=\"value\" :environment=\"env\" />\n *\n * <!-- Boolean select -->\n * <CodeInput v-model=\"flag\" type=\"boolean\" />\n *\n * <!-- JSON editor with linting -->\n * <CodeInput v-model=\"data\" language=\"json\" :lint=\"true\" />\n * ```\n */\nexport default {\n inheritAttrs: false,\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { isDefined } from '@scalar/helpers/array/is-defined'\nimport {\n colorPicker as colorPickerExtension,\n useCodeMirror,\n useDropdown,\n type CodeMirrorLanguage,\n type Extension,\n} from '@scalar/use-codemirror'\nimport {\n CONTEXT_FUNCTION_NAMES,\n getContextFunctionComment,\n isContextFunctionName,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { nanoid } from 'nanoid'\nimport { computed, ref, toRef, useAttrs, watch, type Ref } from 'vue'\n\nimport DataTableInputSelect from '@/v2/components/data-table/DataTableInputSelect.vue'\nimport EnvironmentVariableDropdown from '@/v2/features/environments/components/EnvironmentVariablesDropdown.vue'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nimport { backspaceCommand, pillPlugin } from './code-variable-widget'\n\ntype Props = {\n modelValue: CodeInputModelValue\n /** Environment for variable substitution. Pass undefined to disable environment variables */\n environment: XScalarEnvironment | undefined\n /** Type of the input value, affects rendering mode for booleans */\n type?: string | string[]\n /** Render as disabled text display */\n disabled?: boolean\n /** Show error styling */\n error?: boolean\n /** Layout context affects styling and behavior */\n layout?: ClientLayout\n /** Predefined enum values, triggers select mode */\n enum?: string[]\n /** Example values, triggers select mode */\n examples?: string[]\n /** Default value to show in select mode */\n default?: Props['modelValue']\n /** Allow null in boolean select options */\n nullable?: boolean\n /** Placeholder text for empty input */\n placeholder?: string\n /** Show required indicator */\n required?: boolean\n /** Enable color picker extension */\n colorPicker?: boolean\n /** Show line numbers in editor */\n lineNumbers?: boolean\n /** Enable linting */\n lint?: boolean\n /** Enable line wrapping */\n lineWrapping?: boolean\n /** CodeMirror language mode */\n language?: CodeMirrorLanguage\n /** Additional CodeMirror extensions */\n extensions?: Extension[]\n /** Disable tab key for indentation */\n disableTabIndent?: boolean\n /** Disable enter key */\n disableEnter?: boolean\n /** Disable automatic bracket closing */\n disableCloseBrackets?: boolean\n /** Emit submit event on blur */\n emitOnBlur?: boolean\n /** Enable environment variable pills */\n withVariables?: boolean\n /** Enable fake data suggestions like $guid, $timestamp, etc. Should only be enabled for parameters and request bodies */\n withFakeData?: boolean\n /** Emit change event even if the value is the same */\n alwaysEmitChange?: boolean\n /** Custom change handler, prevents default emit */\n handleFieldChange?: (value: string) => void\n /** Custom submit handler, prevents default emit */\n handleFieldSubmit?: (value: string) => void\n /** Put a linethrough on the input text */\n linethrough?: boolean\n}\n\nconst {\n modelValue,\n environment,\n type,\n disabled = false,\n error = false,\n layout = 'desktop',\n enum: enumProp,\n examples,\n default: defaultProp,\n nullable = false,\n placeholder,\n required,\n colorPicker = false,\n lineNumbers = false,\n lint = false,\n lineWrapping = false,\n language,\n extensions = [],\n disableTabIndent = false,\n disableEnter = false,\n disableCloseBrackets = false,\n emitOnBlur = true,\n alwaysEmitChange = false,\n withVariables = true,\n withFakeData = false,\n handleFieldChange,\n handleFieldSubmit,\n} = defineProps<Props>()\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string]\n 'submit': [value: string, event: KeyboardEvent | FocusEvent]\n 'navigate': [route: { page: 'document'; path: 'environment' }]\n 'blur': [value: string, event: FocusEvent]\n}>()\n\n// ---------------------------------------------------------------------------\n// Component identity and focus state\n\nconst attrs = useAttrs() as { id?: string }\nconst componentId = attrs.id || `id-${nanoid()}`\nconst isFocused = ref(false)\n\n// ---------------------------------------------------------------------------\n// Rendering mode detection\n\n/**\n * Determines if we should render a select dropdown for boolean types.\n */\nconst isBooleanMode = computed((): boolean => {\n if (enumProp?.length) {\n return false\n }\n return type === 'boolean' || (Array.isArray(type) && type.includes('boolean'))\n})\n\n/**\n * Options for boolean select mode.\n */\nconst booleanOptions = computed((): string[] =>\n nullable ? ['true', 'false', 'null'] : ['true', 'false'],\n)\n\n/**\n * Default type when dealing with type arrays.\n * Finds the first non-null type.\n */\nconst defaultType = computed((): string | undefined => {\n if (Array.isArray(type)) {\n return type.find((t) => t !== 'null') ?? 'string'\n }\n return type\n})\n\n// ---------------------------------------------------------------------------\n// Event handlers\n\n/**\n * Handles value changes during typing.\n */\nconst handleChange = (value: string): void => {\n if (!alwaysEmitChange && value === serializeValue(modelValue)) {\n return\n }\n\n // Use custom handler or emit update\n if (handleFieldChange) {\n handleFieldChange(value)\n } else {\n emit('update:modelValue', value)\n }\n}\n\n/**\n * Handles form submission (enter key or blur with emitOnBlur).\n */\nconst handleSubmit = (\n value: string,\n event: KeyboardEvent | FocusEvent,\n): void => {\n if (handleFieldSubmit) {\n handleFieldSubmit(value)\n } else {\n emit('submit', value, event)\n }\n}\n\n/**\n * Handles input blur event.\n */\nconst handleBlur = (value: string, event: FocusEvent): void => {\n isFocused.value = false\n\n if (emitOnBlur && modelValue) {\n handleSubmit(value, event)\n }\n\n emit('blur', value, event)\n}\n\n/**\n * Handles model value updates from select components.\n */\nconst handleSelectChange = (value: string): void =>\n emit('update:modelValue', value)\n\n// ---------------------------------------------------------------------------\n// CodeMirror setup\n\n/**\n * Build extensions array.\n * Note: Extensions are not reactive after initialization.\n */\nconst buildExtensions = (): Extension[] => {\n const extensionsList: Extension[] = [...extensions]\n\n if (colorPicker) {\n extensionsList.push(colorPickerExtension)\n }\n\n return extensionsList\n}\n\n/**\n * Reactive pill plugin for environment variable visualization.\n */\nconst contextFunctionDropdownItems = computed(() =>\n withFakeData\n ? CONTEXT_FUNCTION_NAMES.map((key) => ({\n key,\n description: getContextFunctionComment(key),\n }))\n : [],\n)\n\nconst pillPluginExtension = computed(() =>\n pillPlugin({\n environment,\n isContextFunctionName,\n isReadOnly: layout === 'modal',\n }),\n)\n\n/**\n * Combined extensions for CodeMirror.\n */\nconst codeMirrorExtensions = computed((): Extension[] => [\n ...buildExtensions(),\n pillPluginExtension.value,\n backspaceCommand,\n])\n\nconst codeMirrorRef: Ref<HTMLDivElement | null> = ref(null)\n\n/** Converts the model value to a string for CodeMirror */\nconst serializeValue = (value: CodeInputModelValue): string => {\n if (typeof value === 'string') {\n return value\n }\n return JSON.stringify(value)\n}\n\nconst { codeMirror, setCodeMirrorContent } = useCodeMirror({\n content: toRef(() => serializeValue(modelValue)),\n onChange: (value) => {\n handleChange(value)\n updateDropdownVisibility()\n },\n onFocus: () => {\n isFocused.value = true\n },\n onBlur: handleBlur,\n codeMirrorRef,\n disableTabIndent: toRef(() => disableTabIndent),\n disableEnter: toRef(() => disableEnter),\n disableCloseBrackets: toRef(() => disableCloseBrackets),\n lineNumbers: toRef(() => lineNumbers),\n language: toRef(() => language),\n lint: toRef(() => lint),\n extensions: codeMirrorExtensions,\n placeholder: toRef(() => placeholder),\n})\n\n/**\n * Handle autofocus attribute.\n */\nwatch(codeMirror, () => {\n if (codeMirror.value && Object.hasOwn(attrs, 'autofocus')) {\n codeMirror.value.focus()\n }\n})\n\n// ---------------------------------------------------------------------------\n// Environment variable dropdown\n\nconst showDropdown = ref(false)\nconst dropdownQuery = ref('')\nconst dropdownPosition = ref({ left: 0, top: 0 })\nconst dropdownRef = ref<InstanceType<\n typeof EnvironmentVariableDropdown\n> | null>(null)\n\nconst { handleDropdownSelect, updateDropdownVisibility } = useDropdown({\n codeMirror,\n query: dropdownQuery,\n showDropdown,\n dropdownPosition,\n})\n\n/**\n * Determines if the environment variable dropdown should be visible.\n * Shows when environment is defined (for env vars) or withFakeData is true (for context functions)\n */\nconst displayVariablesDropdown = computed((): boolean => {\n return (\n showDropdown.value &&\n withVariables &&\n layout !== 'modal' &&\n (Boolean(environment) || withFakeData)\n )\n})\n\n// ---------------------------------------------------------------------------\n// Keyboard event handling\n\n/**\n * Handles keyboard navigation for dropdown and form submission.\n */\nconst handleKeyDown = (key: string, event: KeyboardEvent): void => {\n if (showDropdown.value) {\n if (key === 'down' || key === 'up') {\n event.preventDefault()\n dropdownRef.value?.handleArrowKey(key)\n } else if (key === 'enter') {\n event.preventDefault()\n dropdownRef.value?.handleSelect()\n }\n return\n }\n\n if (key === 'escape' && !disableTabIndent) {\n event.stopPropagation()\n }\n\n if (key === 'enter' && event.target instanceof HTMLDivElement) {\n handleSubmit(event.target.textContent ?? '', event)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n\ndefineExpose({\n /**\n * Focus the codemirror element\n *\n * @param cursorAtEnd boolean place the cursor at the end of the input\n */\n focus: (position?: 'start' | 'end' | number) => {\n if (!codeMirror.value) {\n return\n }\n codeMirror.value.focus()\n\n if (!isDefined(position)) {\n return\n }\n\n const anchor = (() => {\n if (position === 'start') {\n return 0\n }\n if (position === 'end') {\n return codeMirror.value.state.doc.length\n }\n return position\n })()\n\n // Move the cursor to the specified position\n codeMirror.value.dispatch({\n selection: { anchor },\n scrollIntoView: true,\n })\n },\n isFocused,\n handleChange,\n handleSubmit,\n handleBlur,\n booleanOptions,\n codeMirror,\n codeMirrorRef,\n modelValue,\n setCodeMirrorContent,\n cursorPosition: () => codeMirror.value?.state.selection.main.head,\n serializeValue,\n})\n</script>\n\n<template>\n <!-- Disabled mode: read-only text display -->\n <div\n v-if=\"disabled\"\n class=\"text-c-2 flex cursor-default items-center justify-center\"\n :class=\"{\n 'font-code pr-2 pl-1 text-base': layout === 'modal',\n 'px-2': layout !== 'modal',\n 'line-through': linethrough,\n }\"\n data-testid=\"code-input-disabled\">\n <span class=\"whitespace-nowrap\">{{ modelValue }}</span>\n </div>\n\n <!-- Enum mode: select dropdown with predefined values -->\n <DataTableInputSelect\n v-else-if=\"enumProp?.length\"\n :default=\"defaultProp\"\n :modelValue=\"modelValue\"\n :type=\"defaultType\"\n :value=\"enumProp\"\n @update:modelValue=\"handleSelectChange\" />\n\n <!-- Boolean mode: select dropdown with true/false (and optionally null) -->\n <DataTableInputSelect\n v-else-if=\"isBooleanMode\"\n :default=\"defaultProp\"\n :modelValue=\"modelValue\"\n :value=\"booleanOptions\"\n @update:modelValue=\"handleSelectChange\" />\n\n <!-- Examples mode: select dropdown with example values -->\n <DataTableInputSelect\n v-else-if=\"examples?.length\"\n :default=\"defaultProp\"\n :modelValue=\"modelValue\"\n :value=\"examples\"\n @update:modelValue=\"handleSelectChange\" />\n\n <!-- Editor mode: CodeMirror with environment variable support -->\n <div\n v-else\n :id=\"componentId\"\n v-bind=\"$attrs\"\n ref=\"codeMirrorRef\"\n class=\"group/input group-[.alert]:outline-orange group-[.error]:outline-red font-code peer relative w-full overflow-hidden text-xs leading-[1.44] whitespace-nowrap -outline-offset-1 has-[:focus-visible]:rounded-[4px] has-[:focus-visible]:outline\"\n :class=\"{\n 'line-wrapping has-[:focus-visible]:bg-b-1 has-[:focus-visible]:absolute has-[:focus-visible]:z-1':\n lineWrapping,\n 'flow-code-input--error': error,\n 'line-through': linethrough,\n }\"\n @keydown.down.stop=\"handleKeyDown('down', $event)\"\n @keydown.enter=\"handleKeyDown('enter', $event)\"\n @keydown.escape=\"handleKeyDown('escape', $event)\"\n @keydown.up.stop=\"handleKeyDown('up', $event)\">\n <!-- Tab exit hint (shown when focused) -->\n <div\n v-if=\"!disableTabIndent\"\n class=\"z-context text-c-2 absolute right-1.5 bottom-1 hidden font-sans group-has-[:focus-visible]/input:block\"\n role=\"alert\">\n Press\n <kbd class=\"-mx-0.25 rounded border px-0.5 font-mono\">Esc</kbd> then\n <kbd class=\"-mx-0.25 rounded border px-0.5 font-mono\">Tab</kbd> to exit\n </div>\n </div>\n\n <!-- Warning slot (positioned absolutely) -->\n <div\n v-if=\"$slots.warning\"\n class=\"centered-y text-orange absolute right-7 text-xs\">\n <slot name=\"warning\" />\n </div>\n\n <!-- Icon slot (positioned absolutely) -->\n <div\n v-if=\"$slots.icon\"\n class=\"centered-y absolute right-0 flex h-full items-center p-1.5 group-has-[.cm-focused]:z-1\">\n <slot name=\"icon\" />\n </div>\n\n <!-- Required indicator -->\n <div\n v-if=\"required\"\n class=\"required centered-y text-xxs text-c-3 group-[.error]:text-red bg-b-1 pointer-events-none absolute right-0 mr-0.5 pt-px pr-2 opacity-100 shadow-[-8px_0_4px_var(--scalar-background-1)] transition-opacity duration-150 group-[.alert]:bg-transparent group-[.alert]:shadow-none group-[.error]:bg-transparent group-[.error]:shadow-none peer-has-[.cm-focused]:opacity-0\">\n Required\n </div>\n\n <!-- Environment variable autocomplete dropdown -->\n <EnvironmentVariableDropdown\n v-if=\"displayVariablesDropdown\"\n ref=\"dropdownRef\"\n :contextFunctionItems=\"contextFunctionDropdownItems\"\n :dropdownPosition=\"dropdownPosition\"\n :environment=\"environment\"\n :query=\"dropdownQuery\"\n @redirect=\"emit('navigate', { page: 'document', path: 'environment' })\"\n @select=\"handleDropdownSelect\" />\n</template>\n<style scoped>\n/*\n Deep styling for customizing Codemirror\n */\n:deep(.cm-editor) {\n height: 100%;\n outline: none;\n padding: 0;\n background: transparent;\n}\n:deep(.cm-placeholder) {\n color: var(--scalar-color-3);\n}\n:deep(.cm-content) {\n font-family: var(--scalar-font-code);\n font-size: var(--scalar-small);\n max-height: 20px;\n padding: 8px 0;\n}\n/* Tooltip helper */\n:deep(.cm-tooltip) {\n background: transparent !important;\n filter: brightness(var(--scalar-lifted-brightness));\n border-radius: var(--scalar-radius);\n box-shadow: var(--scalar-shadow-2);\n border: none !important;\n outline: none !important;\n overflow: hidden !important;\n}\n:deep(.cm-tooltip-autocomplete ul li) {\n padding: 3px 6px !important;\n}\n:deep(.cm-completionIcon-type:after) {\n color: var(--scalar-color-3) !important;\n}\n:deep(.cm-tooltip-autocomplete ul li[aria-selected]) {\n background: var(--scalar-background-2) !important;\n color: var(--scalar-color-1) !important;\n}\n:deep(.cm-tooltip-autocomplete ul) {\n padding: 6px !important;\n position: relative;\n}\n:deep(.cm-tooltip-autocomplete ul li:hover) {\n border-radius: 3px;\n color: var(--scalar-color-1) !important;\n background: var(--scalar-background-3) !important;\n}\n/* Disable active line highlighting */\n:deep(.cm-activeLine),\n:deep(.cm-activeLineGutter) {\n background-color: transparent;\n}\n/* Color selection matching */\n:deep(.cm-selectionMatch),\n:deep(.cm-matchingBracket) {\n border-radius: var(--scalar-radius);\n background: var(--scalar-background-4) !important;\n}\n/* Color Picker Swatches */\n:deep(.cm-css-color-picker-wrapper) {\n display: inline-flex;\n outline: 1px solid var(--scalar-background-3);\n border-radius: 3px;\n overflow: hidden;\n}\n/* Number gutter */\n:deep(.cm-gutters) {\n background-color: transparent;\n border-right: none;\n color: var(--scalar-color-3);\n font-size: var(--scalar-small);\n line-height: 22px;\n border-radius: 0 0 0 3px;\n}\n:deep(.cm-gutters:before) {\n content: '';\n position: absolute;\n top: 2px;\n left: 2px;\n width: calc(100% - 2px);\n height: calc(100% - 4px);\n border-radius: var(--scalar-radius) 0 0 var(--scalar-radius);\n background-color: var(--scalar-background-1);\n}\n:deep(.cm-gutterElement) {\n font-family: var(--scalar-font-code) !important;\n padding-left: 0px !important;\n padding-right: 6px !important;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n position: relative;\n}\n:deep(.cm-lineNumbers .cm-gutterElement) {\n min-width: fit-content;\n}\n:deep(.cm-gutter + .cm-gutter :not(.cm-foldGutter) .cm-gutterElement) {\n padding-left: 0 !important;\n}\n:deep(.cm-scroller) {\n overflow: auto;\n}\n.line-wrapping:focus-within :deep(.cm-content) {\n display: inline-table;\n min-height: fit-content;\n padding: 3px 6px;\n white-space: break-spaces;\n word-break: break-all;\n}\n</style>\n<style>\n.cm-pill {\n color: var(--scalar-color-1) !important;\n padding: 0px 9px;\n border-radius: 3px;\n display: inline-block;\n border-radius: 30px;\n font-size: var(--scalar-small);\n}\n.light-mode .cm-pill {\n background: var(--scalar-background-3) !important;\n}\n.dark-mode .cm-pill {\n background: color-mix(in srgb, var(--tw-bg-base), transparent 90%) !important;\n}\n.cm-pill--context-fn {\n border: 1px dashed color-mix(in srgb, var(--scalar-color-3), transparent 35%);\n padding: 0px 8px;\n}\n.light-mode .cm-pill--context-fn {\n background: color-mix(\n in srgb,\n var(--scalar-background-3),\n transparent 40%\n ) !important;\n}\n.dark-mode .cm-pill--context-fn {\n background: color-mix(\n in srgb,\n var(--scalar-background-3),\n transparent 55%\n ) !important;\n}\n.cm-pill:first-of-type {\n margin-left: 0;\n}\n.cm-editor .cm-widgetBuffer {\n display: none;\n}\n.cm-foldPlaceholder:hover {\n color: var(--scalar-color-1);\n}\n.cm-foldGutter .cm-gutterElement {\n font-size: var(--scalar-heading-4);\n padding: 2px !important;\n}\n.cm-foldGutter .cm-gutterElement:first-of-type {\n display: none;\n}\n.cm-foldGutter .cm-gutterElement .cm-foldMarker {\n padding: 2px;\n padding-top: 2px;\n}\n.cm-foldGutter .cm-gutterElement:hover .cm-foldMarker {\n background: var(--scalar-background-2);\n border-radius: var(--scalar-radius);\n color: var(--scalar-color-1);\n}\n</style>\n"],"mappings":""}

@@ -104,2 +104,6 @@ import DataTableInputSelect_default from "../data-table/DataTableInputSelect.vue.js";

},
withFakeData: {
type: Boolean,
default: false
},
alwaysEmitChange: {

@@ -186,6 +190,6 @@ type: Boolean,

*/
const contextFunctionDropdownItems = computed(() => CONTEXT_FUNCTION_NAMES.map((key) => ({
const contextFunctionDropdownItems = computed(() => __props.withFakeData ? CONTEXT_FUNCTION_NAMES.map((key) => ({
key,
description: getContextFunctionComment(key)
})));
})) : []);
const pillPluginExtension = computed(() => pillPlugin({

@@ -251,5 +255,6 @@ environment: __props.environment,

* Determines if the environment variable dropdown should be visible.
* Shows when environment is defined (for env vars) or withFakeData is true (for context functions)
*/
const displayVariablesDropdown = computed(() => {
return showDropdown.value && __props.withVariables && __props.layout !== "modal" && Boolean(__props.environment);
return showDropdown.value && __props.withVariables && __props.layout !== "modal" && (Boolean(__props.environment) || __props.withFakeData);
});

@@ -369,3 +374,3 @@ /**

__props.required ? (openBlock(), createElementBlock("div", _hoisted_6, " Required ")) : createCommentVNode("", true),
displayVariablesDropdown.value && __props.environment ? (openBlock(), createBlock(EnvironmentVariablesDropdown_default, {
displayVariablesDropdown.value ? (openBlock(), createBlock(EnvironmentVariablesDropdown_default, {
key: 8,

@@ -372,0 +377,0 @@ ref_key: "dropdownRef",

@@ -1,1 +0,1 @@

{"version":3,"file":"CodeInput.vue.script.js","names":["$attrs","$slots"],"sources":["../../../../src/v2/components/code-input/CodeInput.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type CodeInputModelValue =\n | string\n | number\n | boolean\n | Array<string | number | boolean>\n | Record<string, unknown>\n\n/**\n * CodeInput\n *\n * A versatile input component that adapts its rendering based on props:\n * - Disabled mode: Read-only text display\n * - Select mode: Dropdown for enums, booleans, or examples\n * - Editor mode: CodeMirror with environment variable support\n *\n * Type `{{` to trigger autocomplete for environment variables and runtime context functions\n * (for example `{{$guid}}`) when an environment is provided.\n * It takes in any data but always will emit a string value,\n * this string should then be parsed in accordance to the schema or content type.\n *\n * @example\n * ```vue\n * <!-- Basic input with environment variables -->\n * <CodeInput v-model=\"value\" :environment=\"env\" />\n *\n * <!-- Boolean select -->\n * <CodeInput v-model=\"flag\" type=\"boolean\" />\n *\n * <!-- JSON editor with linting -->\n * <CodeInput v-model=\"data\" language=\"json\" :lint=\"true\" />\n * ```\n */\nexport default {\n inheritAttrs: false,\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { isDefined } from '@scalar/helpers/array/is-defined'\nimport {\n colorPicker as colorPickerExtension,\n useCodeMirror,\n useDropdown,\n type CodeMirrorLanguage,\n type Extension,\n} from '@scalar/use-codemirror'\nimport {\n CONTEXT_FUNCTION_NAMES,\n getContextFunctionComment,\n isContextFunctionName,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { nanoid } from 'nanoid'\nimport { computed, ref, toRef, useAttrs, watch, type Ref } from 'vue'\n\nimport DataTableInputSelect from '@/v2/components/data-table/DataTableInputSelect.vue'\nimport EnvironmentVariableDropdown from '@/v2/features/environments/components/EnvironmentVariablesDropdown.vue'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nimport { backspaceCommand, pillPlugin } from './code-variable-widget'\n\ntype Props = {\n modelValue: CodeInputModelValue\n /** Environment for variable substitution. Pass undefined to disable environment variables */\n environment: XScalarEnvironment | undefined\n /** Type of the input value, affects rendering mode for booleans */\n type?: string | string[]\n /** Render as disabled text display */\n disabled?: boolean\n /** Show error styling */\n error?: boolean\n /** Layout context affects styling and behavior */\n layout?: ClientLayout\n /** Predefined enum values, triggers select mode */\n enum?: string[]\n /** Example values, triggers select mode */\n examples?: string[]\n /** Default value to show in select mode */\n default?: Props['modelValue']\n /** Allow null in boolean select options */\n nullable?: boolean\n /** Placeholder text for empty input */\n placeholder?: string\n /** Show required indicator */\n required?: boolean\n /** Enable color picker extension */\n colorPicker?: boolean\n /** Show line numbers in editor */\n lineNumbers?: boolean\n /** Enable linting */\n lint?: boolean\n /** Enable line wrapping */\n lineWrapping?: boolean\n /** CodeMirror language mode */\n language?: CodeMirrorLanguage\n /** Additional CodeMirror extensions */\n extensions?: Extension[]\n /** Disable tab key for indentation */\n disableTabIndent?: boolean\n /** Disable enter key */\n disableEnter?: boolean\n /** Disable automatic bracket closing */\n disableCloseBrackets?: boolean\n /** Emit submit event on blur */\n emitOnBlur?: boolean\n /** Enable environment variable pills */\n withVariables?: boolean\n /** Emit change event even if the value is the same */\n alwaysEmitChange?: boolean\n /** Custom change handler, prevents default emit */\n handleFieldChange?: (value: string) => void\n /** Custom submit handler, prevents default emit */\n handleFieldSubmit?: (value: string) => void\n /** Put a linethrough on the input text */\n linethrough?: boolean\n}\n\nconst {\n modelValue,\n environment,\n type,\n disabled = false,\n error = false,\n layout = 'desktop',\n enum: enumProp,\n examples,\n default: defaultProp,\n nullable = false,\n placeholder,\n required,\n colorPicker = false,\n lineNumbers = false,\n lint = false,\n lineWrapping = false,\n language,\n extensions = [],\n disableTabIndent = false,\n disableEnter = false,\n disableCloseBrackets = false,\n emitOnBlur = true,\n alwaysEmitChange = false,\n withVariables = true,\n handleFieldChange,\n handleFieldSubmit,\n} = defineProps<Props>()\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string]\n 'submit': [value: string, event: KeyboardEvent | FocusEvent]\n 'navigate': [route: { page: 'document'; path: 'environment' }]\n 'blur': [value: string, event: FocusEvent]\n}>()\n\n// ---------------------------------------------------------------------------\n// Component identity and focus state\n\nconst attrs = useAttrs() as { id?: string }\nconst componentId = attrs.id || `id-${nanoid()}`\nconst isFocused = ref(false)\n\n// ---------------------------------------------------------------------------\n// Rendering mode detection\n\n/**\n * Determines if we should render a select dropdown for boolean types.\n */\nconst isBooleanMode = computed((): boolean => {\n if (enumProp?.length) {\n return false\n }\n return type === 'boolean' || (Array.isArray(type) && type.includes('boolean'))\n})\n\n/**\n * Options for boolean select mode.\n */\nconst booleanOptions = computed((): string[] =>\n nullable ? ['true', 'false', 'null'] : ['true', 'false'],\n)\n\n/**\n * Default type when dealing with type arrays.\n * Finds the first non-null type.\n */\nconst defaultType = computed((): string | undefined => {\n if (Array.isArray(type)) {\n return type.find((t) => t !== 'null') ?? 'string'\n }\n return type\n})\n\n// ---------------------------------------------------------------------------\n// Event handlers\n\n/**\n * Handles value changes during typing.\n */\nconst handleChange = (value: string): void => {\n if (!alwaysEmitChange && value === serializeValue(modelValue)) {\n return\n }\n\n // Use custom handler or emit update\n if (handleFieldChange) {\n handleFieldChange(value)\n } else {\n emit('update:modelValue', value)\n }\n}\n\n/**\n * Handles form submission (enter key or blur with emitOnBlur).\n */\nconst handleSubmit = (\n value: string,\n event: KeyboardEvent | FocusEvent,\n): void => {\n if (handleFieldSubmit) {\n handleFieldSubmit(value)\n } else {\n emit('submit', value, event)\n }\n}\n\n/**\n * Handles input blur event.\n */\nconst handleBlur = (value: string, event: FocusEvent): void => {\n isFocused.value = false\n\n if (emitOnBlur && modelValue) {\n handleSubmit(value, event)\n }\n\n emit('blur', value, event)\n}\n\n/**\n * Handles model value updates from select components.\n */\nconst handleSelectChange = (value: string): void =>\n emit('update:modelValue', value)\n\n// ---------------------------------------------------------------------------\n// CodeMirror setup\n\n/**\n * Build extensions array.\n * Note: Extensions are not reactive after initialization.\n */\nconst buildExtensions = (): Extension[] => {\n const extensionsList: Extension[] = [...extensions]\n\n if (colorPicker) {\n extensionsList.push(colorPickerExtension)\n }\n\n return extensionsList\n}\n\n/**\n * Reactive pill plugin for environment variable visualization.\n */\nconst contextFunctionDropdownItems = computed(() =>\n CONTEXT_FUNCTION_NAMES.map((key) => ({\n key,\n description: getContextFunctionComment(key),\n })),\n)\n\nconst pillPluginExtension = computed(() =>\n pillPlugin({\n environment,\n isContextFunctionName,\n isReadOnly: layout === 'modal',\n }),\n)\n\n/**\n * Combined extensions for CodeMirror.\n */\nconst codeMirrorExtensions = computed((): Extension[] => [\n ...buildExtensions(),\n pillPluginExtension.value,\n backspaceCommand,\n])\n\nconst codeMirrorRef: Ref<HTMLDivElement | null> = ref(null)\n\n/** Converts the model value to a string for CodeMirror */\nconst serializeValue = (value: CodeInputModelValue): string => {\n if (typeof value === 'string') {\n return value\n }\n return JSON.stringify(value)\n}\n\nconst { codeMirror, setCodeMirrorContent } = useCodeMirror({\n content: toRef(() => serializeValue(modelValue)),\n onChange: (value) => {\n handleChange(value)\n updateDropdownVisibility()\n },\n onFocus: () => {\n isFocused.value = true\n },\n onBlur: handleBlur,\n codeMirrorRef,\n disableTabIndent: toRef(() => disableTabIndent),\n disableEnter: toRef(() => disableEnter),\n disableCloseBrackets: toRef(() => disableCloseBrackets),\n lineNumbers: toRef(() => lineNumbers),\n language: toRef(() => language),\n lint: toRef(() => lint),\n extensions: codeMirrorExtensions,\n placeholder: toRef(() => placeholder),\n})\n\n/**\n * Handle autofocus attribute.\n */\nwatch(codeMirror, () => {\n if (codeMirror.value && Object.hasOwn(attrs, 'autofocus')) {\n codeMirror.value.focus()\n }\n})\n\n// ---------------------------------------------------------------------------\n// Environment variable dropdown\n\nconst showDropdown = ref(false)\nconst dropdownQuery = ref('')\nconst dropdownPosition = ref({ left: 0, top: 0 })\nconst dropdownRef = ref<InstanceType<\n typeof EnvironmentVariableDropdown\n> | null>(null)\n\nconst { handleDropdownSelect, updateDropdownVisibility } = useDropdown({\n codeMirror,\n query: dropdownQuery,\n showDropdown,\n dropdownPosition,\n})\n\n/**\n * Determines if the environment variable dropdown should be visible.\n */\nconst displayVariablesDropdown = computed((): boolean => {\n return (\n showDropdown.value &&\n withVariables &&\n layout !== 'modal' &&\n Boolean(environment)\n )\n})\n\n// ---------------------------------------------------------------------------\n// Keyboard event handling\n\n/**\n * Handles keyboard navigation for dropdown and form submission.\n */\nconst handleKeyDown = (key: string, event: KeyboardEvent): void => {\n if (showDropdown.value) {\n if (key === 'down' || key === 'up') {\n event.preventDefault()\n dropdownRef.value?.handleArrowKey(key)\n } else if (key === 'enter') {\n event.preventDefault()\n dropdownRef.value?.handleSelect()\n }\n return\n }\n\n if (key === 'escape' && !disableTabIndent) {\n event.stopPropagation()\n }\n\n if (key === 'enter' && event.target instanceof HTMLDivElement) {\n handleSubmit(event.target.textContent ?? '', event)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n\ndefineExpose({\n /**\n * Focus the codemirror element\n *\n * @param cursorAtEnd boolean place the cursor at the end of the input\n */\n focus: (position?: 'start' | 'end' | number) => {\n if (!codeMirror.value) {\n return\n }\n codeMirror.value.focus()\n\n if (!isDefined(position)) {\n return\n }\n\n const anchor = (() => {\n if (position === 'start') {\n return 0\n }\n if (position === 'end') {\n return codeMirror.value.state.doc.length\n }\n return position\n })()\n\n // Move the cursor to the specified position\n codeMirror.value.dispatch({\n selection: { anchor },\n scrollIntoView: true,\n })\n },\n isFocused,\n handleChange,\n handleSubmit,\n handleBlur,\n booleanOptions,\n codeMirror,\n codeMirrorRef,\n modelValue,\n setCodeMirrorContent,\n cursorPosition: () => codeMirror.value?.state.selection.main.head,\n serializeValue,\n})\n</script>\n\n<template>\n <!-- Disabled mode: read-only text display -->\n <div\n v-if=\"disabled\"\n class=\"text-c-2 flex cursor-default items-center justify-center\"\n :class=\"{\n 'font-code pr-2 pl-1 text-base': layout === 'modal',\n 'px-2': layout !== 'modal',\n 'line-through': linethrough,\n }\"\n data-testid=\"code-input-disabled\">\n <span class=\"whitespace-nowrap\">{{ modelValue }}</span>\n </div>\n\n <!-- Enum mode: select dropdown with predefined values -->\n <DataTableInputSelect\n v-else-if=\"enumProp?.length\"\n :default=\"defaultProp\"\n :modelValue=\"modelValue\"\n :type=\"defaultType\"\n :value=\"enumProp\"\n @update:modelValue=\"handleSelectChange\" />\n\n <!-- Boolean mode: select dropdown with true/false (and optionally null) -->\n <DataTableInputSelect\n v-else-if=\"isBooleanMode\"\n :default=\"defaultProp\"\n :modelValue=\"modelValue\"\n :value=\"booleanOptions\"\n @update:modelValue=\"handleSelectChange\" />\n\n <!-- Examples mode: select dropdown with example values -->\n <DataTableInputSelect\n v-else-if=\"examples?.length\"\n :default=\"defaultProp\"\n :modelValue=\"modelValue\"\n :value=\"examples\"\n @update:modelValue=\"handleSelectChange\" />\n\n <!-- Editor mode: CodeMirror with environment variable support -->\n <div\n v-else\n :id=\"componentId\"\n v-bind=\"$attrs\"\n ref=\"codeMirrorRef\"\n class=\"group/input group-[.alert]:outline-orange group-[.error]:outline-red font-code peer relative w-full overflow-hidden text-xs leading-[1.44] whitespace-nowrap -outline-offset-1 has-[:focus-visible]:rounded-[4px] has-[:focus-visible]:outline\"\n :class=\"{\n 'line-wrapping has-[:focus-visible]:bg-b-1 has-[:focus-visible]:absolute has-[:focus-visible]:z-1':\n lineWrapping,\n 'flow-code-input--error': error,\n 'line-through': linethrough,\n }\"\n @keydown.down.stop=\"handleKeyDown('down', $event)\"\n @keydown.enter=\"handleKeyDown('enter', $event)\"\n @keydown.escape=\"handleKeyDown('escape', $event)\"\n @keydown.up.stop=\"handleKeyDown('up', $event)\">\n <!-- Tab exit hint (shown when focused) -->\n <div\n v-if=\"!disableTabIndent\"\n class=\"z-context text-c-2 absolute right-1.5 bottom-1 hidden font-sans group-has-[:focus-visible]/input:block\"\n role=\"alert\">\n Press\n <kbd class=\"-mx-0.25 rounded border px-0.5 font-mono\">Esc</kbd> then\n <kbd class=\"-mx-0.25 rounded border px-0.5 font-mono\">Tab</kbd> to exit\n </div>\n </div>\n\n <!-- Warning slot (positioned absolutely) -->\n <div\n v-if=\"$slots.warning\"\n class=\"centered-y text-orange absolute right-7 text-xs\">\n <slot name=\"warning\" />\n </div>\n\n <!-- Icon slot (positioned absolutely) -->\n <div\n v-if=\"$slots.icon\"\n class=\"centered-y absolute right-0 flex h-full items-center p-1.5 group-has-[.cm-focused]:z-1\">\n <slot name=\"icon\" />\n </div>\n\n <!-- Required indicator -->\n <div\n v-if=\"required\"\n class=\"required centered-y text-xxs text-c-3 group-[.error]:text-red bg-b-1 pointer-events-none absolute right-0 mr-0.5 pt-px pr-2 opacity-100 shadow-[-8px_0_4px_var(--scalar-background-1)] transition-opacity duration-150 group-[.alert]:bg-transparent group-[.alert]:shadow-none group-[.error]:bg-transparent group-[.error]:shadow-none peer-has-[.cm-focused]:opacity-0\">\n Required\n </div>\n\n <!-- Environment variable autocomplete dropdown -->\n <EnvironmentVariableDropdown\n v-if=\"displayVariablesDropdown && environment\"\n ref=\"dropdownRef\"\n :contextFunctionItems=\"contextFunctionDropdownItems\"\n :dropdownPosition=\"dropdownPosition\"\n :environment=\"environment\"\n :query=\"dropdownQuery\"\n @redirect=\"emit('navigate', { page: 'document', path: 'environment' })\"\n @select=\"handleDropdownSelect\" />\n</template>\n<style scoped>\n/*\n Deep styling for customizing Codemirror\n */\n:deep(.cm-editor) {\n height: 100%;\n outline: none;\n padding: 0;\n background: transparent;\n}\n:deep(.cm-placeholder) {\n color: var(--scalar-color-3);\n}\n:deep(.cm-content) {\n font-family: var(--scalar-font-code);\n font-size: var(--scalar-small);\n max-height: 20px;\n padding: 8px 0;\n}\n/* Tooltip helper */\n:deep(.cm-tooltip) {\n background: transparent !important;\n filter: brightness(var(--scalar-lifted-brightness));\n border-radius: var(--scalar-radius);\n box-shadow: var(--scalar-shadow-2);\n border: none !important;\n outline: none !important;\n overflow: hidden !important;\n}\n:deep(.cm-tooltip-autocomplete ul li) {\n padding: 3px 6px !important;\n}\n:deep(.cm-completionIcon-type:after) {\n color: var(--scalar-color-3) !important;\n}\n:deep(.cm-tooltip-autocomplete ul li[aria-selected]) {\n background: var(--scalar-background-2) !important;\n color: var(--scalar-color-1) !important;\n}\n:deep(.cm-tooltip-autocomplete ul) {\n padding: 6px !important;\n position: relative;\n}\n:deep(.cm-tooltip-autocomplete ul li:hover) {\n border-radius: 3px;\n color: var(--scalar-color-1) !important;\n background: var(--scalar-background-3) !important;\n}\n/* Disable active line highlighting */\n:deep(.cm-activeLine),\n:deep(.cm-activeLineGutter) {\n background-color: transparent;\n}\n/* Color selection matching */\n:deep(.cm-selectionMatch),\n:deep(.cm-matchingBracket) {\n border-radius: var(--scalar-radius);\n background: var(--scalar-background-4) !important;\n}\n/* Color Picker Swatches */\n:deep(.cm-css-color-picker-wrapper) {\n display: inline-flex;\n outline: 1px solid var(--scalar-background-3);\n border-radius: 3px;\n overflow: hidden;\n}\n/* Number gutter */\n:deep(.cm-gutters) {\n background-color: transparent;\n border-right: none;\n color: var(--scalar-color-3);\n font-size: var(--scalar-small);\n line-height: 22px;\n border-radius: 0 0 0 3px;\n}\n:deep(.cm-gutters:before) {\n content: '';\n position: absolute;\n top: 2px;\n left: 2px;\n width: calc(100% - 2px);\n height: calc(100% - 4px);\n border-radius: var(--scalar-radius) 0 0 var(--scalar-radius);\n background-color: var(--scalar-background-1);\n}\n:deep(.cm-gutterElement) {\n font-family: var(--scalar-font-code) !important;\n padding-left: 0px !important;\n padding-right: 6px !important;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n position: relative;\n}\n:deep(.cm-lineNumbers .cm-gutterElement) {\n min-width: fit-content;\n}\n:deep(.cm-gutter + .cm-gutter :not(.cm-foldGutter) .cm-gutterElement) {\n padding-left: 0 !important;\n}\n:deep(.cm-scroller) {\n overflow: auto;\n}\n.line-wrapping:focus-within :deep(.cm-content) {\n display: inline-table;\n min-height: fit-content;\n padding: 3px 6px;\n white-space: break-spaces;\n word-break: break-all;\n}\n</style>\n<style>\n.cm-pill {\n color: var(--scalar-color-1) !important;\n padding: 0px 9px;\n border-radius: 3px;\n display: inline-block;\n border-radius: 30px;\n font-size: var(--scalar-small);\n}\n.light-mode .cm-pill {\n background: var(--scalar-background-3) !important;\n}\n.dark-mode .cm-pill {\n background: color-mix(in srgb, var(--tw-bg-base), transparent 90%) !important;\n}\n.cm-pill--context-fn {\n border: 1px dashed color-mix(in srgb, var(--scalar-color-3), transparent 35%);\n padding: 0px 8px;\n}\n.light-mode .cm-pill--context-fn {\n background: color-mix(\n in srgb,\n var(--scalar-background-3),\n transparent 40%\n ) !important;\n}\n.dark-mode .cm-pill--context-fn {\n background: color-mix(\n in srgb,\n var(--scalar-background-3),\n transparent 55%\n ) !important;\n}\n.cm-pill:first-of-type {\n margin-left: 0;\n}\n.cm-editor .cm-widgetBuffer {\n display: none;\n}\n.cm-foldPlaceholder:hover {\n color: var(--scalar-color-1);\n}\n.cm-foldGutter .cm-gutterElement {\n font-size: var(--scalar-heading-4);\n padding: 2px !important;\n}\n.cm-foldGutter .cm-gutterElement:first-of-type {\n display: none;\n}\n.cm-foldGutter .cm-gutterElement .cm-foldMarker {\n padding: 2px;\n padding-top: 2px;\n}\n.cm-foldGutter .cm-gutterElement:hover .cm-foldMarker {\n background: var(--scalar-background-2);\n border-radius: var(--scalar-radius);\n color: var(--scalar-color-1);\n}\n</style>\n"],"mappings":"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"}
{"version":3,"file":"CodeInput.vue.script.js","names":["$attrs","$slots"],"sources":["../../../../src/v2/components/code-input/CodeInput.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type CodeInputModelValue =\n | string\n | number\n | boolean\n | Array<string | number | boolean>\n | Record<string, unknown>\n\n/**\n * CodeInput\n *\n * A versatile input component that adapts its rendering based on props:\n * - Disabled mode: Read-only text display\n * - Select mode: Dropdown for enums, booleans, or examples\n * - Editor mode: CodeMirror with environment variable support\n *\n * Type `{{` to trigger autocomplete for environment variables and runtime context functions\n * (for example `{{$guid}}`) when an environment is provided.\n * It takes in any data but always will emit a string value,\n * this string should then be parsed in accordance to the schema or content type.\n *\n * @example\n * ```vue\n * <!-- Basic input with environment variables -->\n * <CodeInput v-model=\"value\" :environment=\"env\" />\n *\n * <!-- Boolean select -->\n * <CodeInput v-model=\"flag\" type=\"boolean\" />\n *\n * <!-- JSON editor with linting -->\n * <CodeInput v-model=\"data\" language=\"json\" :lint=\"true\" />\n * ```\n */\nexport default {\n inheritAttrs: false,\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { isDefined } from '@scalar/helpers/array/is-defined'\nimport {\n colorPicker as colorPickerExtension,\n useCodeMirror,\n useDropdown,\n type CodeMirrorLanguage,\n type Extension,\n} from '@scalar/use-codemirror'\nimport {\n CONTEXT_FUNCTION_NAMES,\n getContextFunctionComment,\n isContextFunctionName,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { nanoid } from 'nanoid'\nimport { computed, ref, toRef, useAttrs, watch, type Ref } from 'vue'\n\nimport DataTableInputSelect from '@/v2/components/data-table/DataTableInputSelect.vue'\nimport EnvironmentVariableDropdown from '@/v2/features/environments/components/EnvironmentVariablesDropdown.vue'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nimport { backspaceCommand, pillPlugin } from './code-variable-widget'\n\ntype Props = {\n modelValue: CodeInputModelValue\n /** Environment for variable substitution. Pass undefined to disable environment variables */\n environment: XScalarEnvironment | undefined\n /** Type of the input value, affects rendering mode for booleans */\n type?: string | string[]\n /** Render as disabled text display */\n disabled?: boolean\n /** Show error styling */\n error?: boolean\n /** Layout context affects styling and behavior */\n layout?: ClientLayout\n /** Predefined enum values, triggers select mode */\n enum?: string[]\n /** Example values, triggers select mode */\n examples?: string[]\n /** Default value to show in select mode */\n default?: Props['modelValue']\n /** Allow null in boolean select options */\n nullable?: boolean\n /** Placeholder text for empty input */\n placeholder?: string\n /** Show required indicator */\n required?: boolean\n /** Enable color picker extension */\n colorPicker?: boolean\n /** Show line numbers in editor */\n lineNumbers?: boolean\n /** Enable linting */\n lint?: boolean\n /** Enable line wrapping */\n lineWrapping?: boolean\n /** CodeMirror language mode */\n language?: CodeMirrorLanguage\n /** Additional CodeMirror extensions */\n extensions?: Extension[]\n /** Disable tab key for indentation */\n disableTabIndent?: boolean\n /** Disable enter key */\n disableEnter?: boolean\n /** Disable automatic bracket closing */\n disableCloseBrackets?: boolean\n /** Emit submit event on blur */\n emitOnBlur?: boolean\n /** Enable environment variable pills */\n withVariables?: boolean\n /** Enable fake data suggestions like $guid, $timestamp, etc. Should only be enabled for parameters and request bodies */\n withFakeData?: boolean\n /** Emit change event even if the value is the same */\n alwaysEmitChange?: boolean\n /** Custom change handler, prevents default emit */\n handleFieldChange?: (value: string) => void\n /** Custom submit handler, prevents default emit */\n handleFieldSubmit?: (value: string) => void\n /** Put a linethrough on the input text */\n linethrough?: boolean\n}\n\nconst {\n modelValue,\n environment,\n type,\n disabled = false,\n error = false,\n layout = 'desktop',\n enum: enumProp,\n examples,\n default: defaultProp,\n nullable = false,\n placeholder,\n required,\n colorPicker = false,\n lineNumbers = false,\n lint = false,\n lineWrapping = false,\n language,\n extensions = [],\n disableTabIndent = false,\n disableEnter = false,\n disableCloseBrackets = false,\n emitOnBlur = true,\n alwaysEmitChange = false,\n withVariables = true,\n withFakeData = false,\n handleFieldChange,\n handleFieldSubmit,\n} = defineProps<Props>()\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: string]\n 'submit': [value: string, event: KeyboardEvent | FocusEvent]\n 'navigate': [route: { page: 'document'; path: 'environment' }]\n 'blur': [value: string, event: FocusEvent]\n}>()\n\n// ---------------------------------------------------------------------------\n// Component identity and focus state\n\nconst attrs = useAttrs() as { id?: string }\nconst componentId = attrs.id || `id-${nanoid()}`\nconst isFocused = ref(false)\n\n// ---------------------------------------------------------------------------\n// Rendering mode detection\n\n/**\n * Determines if we should render a select dropdown for boolean types.\n */\nconst isBooleanMode = computed((): boolean => {\n if (enumProp?.length) {\n return false\n }\n return type === 'boolean' || (Array.isArray(type) && type.includes('boolean'))\n})\n\n/**\n * Options for boolean select mode.\n */\nconst booleanOptions = computed((): string[] =>\n nullable ? ['true', 'false', 'null'] : ['true', 'false'],\n)\n\n/**\n * Default type when dealing with type arrays.\n * Finds the first non-null type.\n */\nconst defaultType = computed((): string | undefined => {\n if (Array.isArray(type)) {\n return type.find((t) => t !== 'null') ?? 'string'\n }\n return type\n})\n\n// ---------------------------------------------------------------------------\n// Event handlers\n\n/**\n * Handles value changes during typing.\n */\nconst handleChange = (value: string): void => {\n if (!alwaysEmitChange && value === serializeValue(modelValue)) {\n return\n }\n\n // Use custom handler or emit update\n if (handleFieldChange) {\n handleFieldChange(value)\n } else {\n emit('update:modelValue', value)\n }\n}\n\n/**\n * Handles form submission (enter key or blur with emitOnBlur).\n */\nconst handleSubmit = (\n value: string,\n event: KeyboardEvent | FocusEvent,\n): void => {\n if (handleFieldSubmit) {\n handleFieldSubmit(value)\n } else {\n emit('submit', value, event)\n }\n}\n\n/**\n * Handles input blur event.\n */\nconst handleBlur = (value: string, event: FocusEvent): void => {\n isFocused.value = false\n\n if (emitOnBlur && modelValue) {\n handleSubmit(value, event)\n }\n\n emit('blur', value, event)\n}\n\n/**\n * Handles model value updates from select components.\n */\nconst handleSelectChange = (value: string): void =>\n emit('update:modelValue', value)\n\n// ---------------------------------------------------------------------------\n// CodeMirror setup\n\n/**\n * Build extensions array.\n * Note: Extensions are not reactive after initialization.\n */\nconst buildExtensions = (): Extension[] => {\n const extensionsList: Extension[] = [...extensions]\n\n if (colorPicker) {\n extensionsList.push(colorPickerExtension)\n }\n\n return extensionsList\n}\n\n/**\n * Reactive pill plugin for environment variable visualization.\n */\nconst contextFunctionDropdownItems = computed(() =>\n withFakeData\n ? CONTEXT_FUNCTION_NAMES.map((key) => ({\n key,\n description: getContextFunctionComment(key),\n }))\n : [],\n)\n\nconst pillPluginExtension = computed(() =>\n pillPlugin({\n environment,\n isContextFunctionName,\n isReadOnly: layout === 'modal',\n }),\n)\n\n/**\n * Combined extensions for CodeMirror.\n */\nconst codeMirrorExtensions = computed((): Extension[] => [\n ...buildExtensions(),\n pillPluginExtension.value,\n backspaceCommand,\n])\n\nconst codeMirrorRef: Ref<HTMLDivElement | null> = ref(null)\n\n/** Converts the model value to a string for CodeMirror */\nconst serializeValue = (value: CodeInputModelValue): string => {\n if (typeof value === 'string') {\n return value\n }\n return JSON.stringify(value)\n}\n\nconst { codeMirror, setCodeMirrorContent } = useCodeMirror({\n content: toRef(() => serializeValue(modelValue)),\n onChange: (value) => {\n handleChange(value)\n updateDropdownVisibility()\n },\n onFocus: () => {\n isFocused.value = true\n },\n onBlur: handleBlur,\n codeMirrorRef,\n disableTabIndent: toRef(() => disableTabIndent),\n disableEnter: toRef(() => disableEnter),\n disableCloseBrackets: toRef(() => disableCloseBrackets),\n lineNumbers: toRef(() => lineNumbers),\n language: toRef(() => language),\n lint: toRef(() => lint),\n extensions: codeMirrorExtensions,\n placeholder: toRef(() => placeholder),\n})\n\n/**\n * Handle autofocus attribute.\n */\nwatch(codeMirror, () => {\n if (codeMirror.value && Object.hasOwn(attrs, 'autofocus')) {\n codeMirror.value.focus()\n }\n})\n\n// ---------------------------------------------------------------------------\n// Environment variable dropdown\n\nconst showDropdown = ref(false)\nconst dropdownQuery = ref('')\nconst dropdownPosition = ref({ left: 0, top: 0 })\nconst dropdownRef = ref<InstanceType<\n typeof EnvironmentVariableDropdown\n> | null>(null)\n\nconst { handleDropdownSelect, updateDropdownVisibility } = useDropdown({\n codeMirror,\n query: dropdownQuery,\n showDropdown,\n dropdownPosition,\n})\n\n/**\n * Determines if the environment variable dropdown should be visible.\n * Shows when environment is defined (for env vars) or withFakeData is true (for context functions)\n */\nconst displayVariablesDropdown = computed((): boolean => {\n return (\n showDropdown.value &&\n withVariables &&\n layout !== 'modal' &&\n (Boolean(environment) || withFakeData)\n )\n})\n\n// ---------------------------------------------------------------------------\n// Keyboard event handling\n\n/**\n * Handles keyboard navigation for dropdown and form submission.\n */\nconst handleKeyDown = (key: string, event: KeyboardEvent): void => {\n if (showDropdown.value) {\n if (key === 'down' || key === 'up') {\n event.preventDefault()\n dropdownRef.value?.handleArrowKey(key)\n } else if (key === 'enter') {\n event.preventDefault()\n dropdownRef.value?.handleSelect()\n }\n return\n }\n\n if (key === 'escape' && !disableTabIndent) {\n event.stopPropagation()\n }\n\n if (key === 'enter' && event.target instanceof HTMLDivElement) {\n handleSubmit(event.target.textContent ?? '', event)\n }\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n\ndefineExpose({\n /**\n * Focus the codemirror element\n *\n * @param cursorAtEnd boolean place the cursor at the end of the input\n */\n focus: (position?: 'start' | 'end' | number) => {\n if (!codeMirror.value) {\n return\n }\n codeMirror.value.focus()\n\n if (!isDefined(position)) {\n return\n }\n\n const anchor = (() => {\n if (position === 'start') {\n return 0\n }\n if (position === 'end') {\n return codeMirror.value.state.doc.length\n }\n return position\n })()\n\n // Move the cursor to the specified position\n codeMirror.value.dispatch({\n selection: { anchor },\n scrollIntoView: true,\n })\n },\n isFocused,\n handleChange,\n handleSubmit,\n handleBlur,\n booleanOptions,\n codeMirror,\n codeMirrorRef,\n modelValue,\n setCodeMirrorContent,\n cursorPosition: () => codeMirror.value?.state.selection.main.head,\n serializeValue,\n})\n</script>\n\n<template>\n <!-- Disabled mode: read-only text display -->\n <div\n v-if=\"disabled\"\n class=\"text-c-2 flex cursor-default items-center justify-center\"\n :class=\"{\n 'font-code pr-2 pl-1 text-base': layout === 'modal',\n 'px-2': layout !== 'modal',\n 'line-through': linethrough,\n }\"\n data-testid=\"code-input-disabled\">\n <span class=\"whitespace-nowrap\">{{ modelValue }}</span>\n </div>\n\n <!-- Enum mode: select dropdown with predefined values -->\n <DataTableInputSelect\n v-else-if=\"enumProp?.length\"\n :default=\"defaultProp\"\n :modelValue=\"modelValue\"\n :type=\"defaultType\"\n :value=\"enumProp\"\n @update:modelValue=\"handleSelectChange\" />\n\n <!-- Boolean mode: select dropdown with true/false (and optionally null) -->\n <DataTableInputSelect\n v-else-if=\"isBooleanMode\"\n :default=\"defaultProp\"\n :modelValue=\"modelValue\"\n :value=\"booleanOptions\"\n @update:modelValue=\"handleSelectChange\" />\n\n <!-- Examples mode: select dropdown with example values -->\n <DataTableInputSelect\n v-else-if=\"examples?.length\"\n :default=\"defaultProp\"\n :modelValue=\"modelValue\"\n :value=\"examples\"\n @update:modelValue=\"handleSelectChange\" />\n\n <!-- Editor mode: CodeMirror with environment variable support -->\n <div\n v-else\n :id=\"componentId\"\n v-bind=\"$attrs\"\n ref=\"codeMirrorRef\"\n class=\"group/input group-[.alert]:outline-orange group-[.error]:outline-red font-code peer relative w-full overflow-hidden text-xs leading-[1.44] whitespace-nowrap -outline-offset-1 has-[:focus-visible]:rounded-[4px] has-[:focus-visible]:outline\"\n :class=\"{\n 'line-wrapping has-[:focus-visible]:bg-b-1 has-[:focus-visible]:absolute has-[:focus-visible]:z-1':\n lineWrapping,\n 'flow-code-input--error': error,\n 'line-through': linethrough,\n }\"\n @keydown.down.stop=\"handleKeyDown('down', $event)\"\n @keydown.enter=\"handleKeyDown('enter', $event)\"\n @keydown.escape=\"handleKeyDown('escape', $event)\"\n @keydown.up.stop=\"handleKeyDown('up', $event)\">\n <!-- Tab exit hint (shown when focused) -->\n <div\n v-if=\"!disableTabIndent\"\n class=\"z-context text-c-2 absolute right-1.5 bottom-1 hidden font-sans group-has-[:focus-visible]/input:block\"\n role=\"alert\">\n Press\n <kbd class=\"-mx-0.25 rounded border px-0.5 font-mono\">Esc</kbd> then\n <kbd class=\"-mx-0.25 rounded border px-0.5 font-mono\">Tab</kbd> to exit\n </div>\n </div>\n\n <!-- Warning slot (positioned absolutely) -->\n <div\n v-if=\"$slots.warning\"\n class=\"centered-y text-orange absolute right-7 text-xs\">\n <slot name=\"warning\" />\n </div>\n\n <!-- Icon slot (positioned absolutely) -->\n <div\n v-if=\"$slots.icon\"\n class=\"centered-y absolute right-0 flex h-full items-center p-1.5 group-has-[.cm-focused]:z-1\">\n <slot name=\"icon\" />\n </div>\n\n <!-- Required indicator -->\n <div\n v-if=\"required\"\n class=\"required centered-y text-xxs text-c-3 group-[.error]:text-red bg-b-1 pointer-events-none absolute right-0 mr-0.5 pt-px pr-2 opacity-100 shadow-[-8px_0_4px_var(--scalar-background-1)] transition-opacity duration-150 group-[.alert]:bg-transparent group-[.alert]:shadow-none group-[.error]:bg-transparent group-[.error]:shadow-none peer-has-[.cm-focused]:opacity-0\">\n Required\n </div>\n\n <!-- Environment variable autocomplete dropdown -->\n <EnvironmentVariableDropdown\n v-if=\"displayVariablesDropdown\"\n ref=\"dropdownRef\"\n :contextFunctionItems=\"contextFunctionDropdownItems\"\n :dropdownPosition=\"dropdownPosition\"\n :environment=\"environment\"\n :query=\"dropdownQuery\"\n @redirect=\"emit('navigate', { page: 'document', path: 'environment' })\"\n @select=\"handleDropdownSelect\" />\n</template>\n<style scoped>\n/*\n Deep styling for customizing Codemirror\n */\n:deep(.cm-editor) {\n height: 100%;\n outline: none;\n padding: 0;\n background: transparent;\n}\n:deep(.cm-placeholder) {\n color: var(--scalar-color-3);\n}\n:deep(.cm-content) {\n font-family: var(--scalar-font-code);\n font-size: var(--scalar-small);\n max-height: 20px;\n padding: 8px 0;\n}\n/* Tooltip helper */\n:deep(.cm-tooltip) {\n background: transparent !important;\n filter: brightness(var(--scalar-lifted-brightness));\n border-radius: var(--scalar-radius);\n box-shadow: var(--scalar-shadow-2);\n border: none !important;\n outline: none !important;\n overflow: hidden !important;\n}\n:deep(.cm-tooltip-autocomplete ul li) {\n padding: 3px 6px !important;\n}\n:deep(.cm-completionIcon-type:after) {\n color: var(--scalar-color-3) !important;\n}\n:deep(.cm-tooltip-autocomplete ul li[aria-selected]) {\n background: var(--scalar-background-2) !important;\n color: var(--scalar-color-1) !important;\n}\n:deep(.cm-tooltip-autocomplete ul) {\n padding: 6px !important;\n position: relative;\n}\n:deep(.cm-tooltip-autocomplete ul li:hover) {\n border-radius: 3px;\n color: var(--scalar-color-1) !important;\n background: var(--scalar-background-3) !important;\n}\n/* Disable active line highlighting */\n:deep(.cm-activeLine),\n:deep(.cm-activeLineGutter) {\n background-color: transparent;\n}\n/* Color selection matching */\n:deep(.cm-selectionMatch),\n:deep(.cm-matchingBracket) {\n border-radius: var(--scalar-radius);\n background: var(--scalar-background-4) !important;\n}\n/* Color Picker Swatches */\n:deep(.cm-css-color-picker-wrapper) {\n display: inline-flex;\n outline: 1px solid var(--scalar-background-3);\n border-radius: 3px;\n overflow: hidden;\n}\n/* Number gutter */\n:deep(.cm-gutters) {\n background-color: transparent;\n border-right: none;\n color: var(--scalar-color-3);\n font-size: var(--scalar-small);\n line-height: 22px;\n border-radius: 0 0 0 3px;\n}\n:deep(.cm-gutters:before) {\n content: '';\n position: absolute;\n top: 2px;\n left: 2px;\n width: calc(100% - 2px);\n height: calc(100% - 4px);\n border-radius: var(--scalar-radius) 0 0 var(--scalar-radius);\n background-color: var(--scalar-background-1);\n}\n:deep(.cm-gutterElement) {\n font-family: var(--scalar-font-code) !important;\n padding-left: 0px !important;\n padding-right: 6px !important;\n display: flex;\n align-items: center;\n justify-content: flex-end;\n position: relative;\n}\n:deep(.cm-lineNumbers .cm-gutterElement) {\n min-width: fit-content;\n}\n:deep(.cm-gutter + .cm-gutter :not(.cm-foldGutter) .cm-gutterElement) {\n padding-left: 0 !important;\n}\n:deep(.cm-scroller) {\n overflow: auto;\n}\n.line-wrapping:focus-within :deep(.cm-content) {\n display: inline-table;\n min-height: fit-content;\n padding: 3px 6px;\n white-space: break-spaces;\n word-break: break-all;\n}\n</style>\n<style>\n.cm-pill {\n color: var(--scalar-color-1) !important;\n padding: 0px 9px;\n border-radius: 3px;\n display: inline-block;\n border-radius: 30px;\n font-size: var(--scalar-small);\n}\n.light-mode .cm-pill {\n background: var(--scalar-background-3) !important;\n}\n.dark-mode .cm-pill {\n background: color-mix(in srgb, var(--tw-bg-base), transparent 90%) !important;\n}\n.cm-pill--context-fn {\n border: 1px dashed color-mix(in srgb, var(--scalar-color-3), transparent 35%);\n padding: 0px 8px;\n}\n.light-mode .cm-pill--context-fn {\n background: color-mix(\n in srgb,\n var(--scalar-background-3),\n transparent 40%\n ) !important;\n}\n.dark-mode .cm-pill--context-fn {\n background: color-mix(\n in srgb,\n var(--scalar-background-3),\n transparent 55%\n ) !important;\n}\n.cm-pill:first-of-type {\n margin-left: 0;\n}\n.cm-editor .cm-widgetBuffer {\n display: none;\n}\n.cm-foldPlaceholder:hover {\n color: var(--scalar-color-1);\n}\n.cm-foldGutter .cm-gutterElement {\n font-size: var(--scalar-heading-4);\n padding: 2px !important;\n}\n.cm-foldGutter .cm-gutterElement:first-of-type {\n display: none;\n}\n.cm-foldGutter .cm-gutterElement .cm-foldMarker {\n padding: 2px;\n padding-top: 2px;\n}\n.cm-foldGutter .cm-gutterElement:hover .cm-foldMarker {\n background: var(--scalar-background-2);\n border-radius: var(--scalar-radius);\n color: var(--scalar-color-1);\n}\n</style>\n"],"mappings":"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"}

@@ -19,2 +19,4 @@ import type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments';

lineWrapping?: boolean;
/** Whether to show context function suggestions like $guid, $timestamp. Defaults to true */
withFakeData?: boolean;
};

@@ -42,2 +44,3 @@ declare var __VLS_8: {}, __VLS_28: {}, __VLS_30: {};

lineWrapping: boolean;
withFakeData: boolean;
canAddCustomEnumValue: boolean;

@@ -44,0 +47,0 @@ readOnly: boolean;

@@ -1,1 +0,1 @@

{"version":3,"file":"DataTableInput.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/components/data-table/DataTableInput.vue"],"names":[],"mappings":"AAwMA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2EAA2E,CAAA;AAGnH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAM/C,KAAK,WAAW,GAAG;IACf,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,sEAAsE;IACtE,cAAc,CAAC,EAAE,YAAY,GAAG,SAAS,CAAA;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,0EAA0E;IAC1E,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,kBAAkB,CAAA;IAC/B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAChC,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB,CAAC;AAmWJ,QAAA,IAAI,OAAO,IAAU,EAAuB,QAAQ,IAAW,EAAE,QAAQ,IAAY,CAAE;AACvF,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,GAC5C;IAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,GAC7C;IAAE,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,CAAC;AAO7C,QAAA,MAAM,UAAU;;;;;;;;;;;cAzXD,OAAO;kBAUH,OAAO;2BAPE,OAAO;cACpB,OAAO;6EAyXpB,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AAWzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
{"version":3,"file":"DataTableInput.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/components/data-table/DataTableInput.vue"],"names":[],"mappings":"AA4MA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2EAA2E,CAAA;AAGnH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAM/C,KAAK,WAAW,GAAG;IACf,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,sEAAsE;IACtE,cAAc,CAAC,EAAE,YAAY,GAAG,SAAS,CAAA;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,0EAA0E;IAC1E,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;IACf,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,kBAAkB,CAAA;IAC/B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAChC,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,4FAA4F;IAC5F,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB,CAAC;AAuWJ,QAAA,IAAI,OAAO,IAAU,EAAuB,QAAQ,IAAW,EAAE,QAAQ,IAAY,CAAE;AACvF,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,GAC5C;IAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,GAC7C;IAAE,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,CAAC;AAO7C,QAAA,MAAM,UAAU;;;;;;;;;;;cA/XD,OAAO;kBAUH,OAAO;kBAEP,OAAO;2BATE,OAAO;cACpB,OAAO;6EA+XpB,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AAWzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}

@@ -5,3 +5,3 @@ import _plugin_vue_export_helper_default from "../../../_virtual/_plugin-vue_export-helper.js";

//#region src/v2/components/data-table/DataTableInput.vue
var DataTableInput_default = /* @__PURE__ */ _plugin_vue_export_helper_default(DataTableInput_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-3157c3c7"]]);
var DataTableInput_default = /* @__PURE__ */ _plugin_vue_export_helper_default(DataTableInput_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-819cea32"]]);
//#endregion

@@ -8,0 +8,0 @@ export { DataTableInput_default as default };

@@ -1,1 +0,1 @@

{"version":3,"file":"DataTableInput.vue.js","names":[],"sources":["../../../../src/v2/components/data-table/DataTableInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarIconButton } from '@scalar/components'\nimport { ScalarIconEye, ScalarIconEyeSlash, ScalarIconX } from '@scalar/icons'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { computed, ref, useTemplateRef } from 'vue'\n\nimport type { VueClassProp } from '@/types/vue'\nimport { CodeInput } from '@/v2/components/code-input'\n\nimport DataTableCell from './DataTableCell.vue'\nimport DataTableInputSelect from './DataTableInputSelect.vue'\n\nconst props = withDefaults(\n defineProps<{\n id?: string\n type?: string | undefined\n /** Class for the wrapping cell because attrs is bound to the input */\n containerClass?: VueClassProp | undefined\n required?: boolean\n modelValue: string\n /** Allows adding a custom value to the enum dropdown, defaults to true */\n canAddCustomEnumValue?: boolean\n readOnly?: boolean\n enum?: string[]\n min?: number\n max?: number\n environment: XScalarEnvironment\n description?: string | undefined\n lineWrapping?: boolean\n }>(),\n {\n canAddCustomEnumValue: true,\n required: false,\n readOnly: false,\n lineWrapping: false,\n },\n)\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', v: string | number): void\n (e: 'inputFocus'): void\n (e: 'inputBlur'): void\n (e: 'selectVariable', value: string): void\n}>()\n\ndefineOptions({ inheritAttrs: false })\n\nconst mask = ref(true)\nconst interactingWithDropdown = ref(false)\nconst codeInput = useTemplateRef('codeInput')\n\nconst handleBlur = () => !interactingWithDropdown.value && emit('inputBlur')\n\nconst inputType = computed(() =>\n props.type === 'password' ? 'text' : (props.type ?? 'text'),\n)\n\n// If not an enum nor read only, focus the code input\nconst handleLabelClick = () => {\n if (!props.enum?.length && !props.readOnly) {\n codeInput.value?.focus()\n }\n}\n</script>\n<template>\n <DataTableCell\n class=\"relative flex\"\n :class=\"containerClass\">\n <div\n v-if=\"$slots.default\"\n class=\"text-c-1 flex items-center pr-0 pl-3\"\n :for=\"id ?? ''\"\n @click=\"handleLabelClick\">\n <slot />:\n </div>\n <div class=\"relative flex min-w-0 flex-1\">\n <template v-if=\"props.enum && props.enum.length\">\n <DataTableInputSelect\n :canAddCustomValue=\"props.canAddCustomEnumValue\"\n :modelValue=\"props.modelValue\"\n :value=\"props.enum\"\n @update:modelValue=\"emit('update:modelValue', $event)\" />\n </template>\n <template v-else>\n <input\n v-if=\"mask && type === 'password'\"\n v-bind=\"id ? { ...$attrs, id: id } : $attrs\"\n autocomplete=\"off\"\n class=\"text-c-1 disabled:text-c-2 peer w-full min-w-0 border-none px-2 py-1.25 -outline-offset-1\"\n :class=\"{ 'scalar-password-input': type === 'password' }\"\n data-1p-ignore\n :readOnly=\"readOnly\"\n spellcheck=\"false\"\n :type=\"inputType\"\n :value=\"modelValue\"\n @input=\"\n emit(\n 'update:modelValue',\n ($event.target as HTMLInputElement).value ?? '',\n )\n \" />\n <CodeInput\n v-else\n v-bind=\"$attrs\"\n :id=\"id\"\n ref=\"codeInput\"\n class=\"text-c-1 disabled:text-c-2 peer w-full min-w-0 border-none -outline-offset-1\"\n :class=\"[\n type === 'password' && description && 'pr-12',\n description && 'pr-8',\n type === 'password' && 'scalar-password-input',\n ]\"\n :description=\"description\"\n disableCloseBrackets\n disableTabIndent\n :environment=\"environment\"\n :lineWrapping=\"Boolean(lineWrapping)\"\n :max=\"max\"\n :min=\"min\"\n :modelValue=\"modelValue ?? ''\"\n :readOnly=\"readOnly\"\n :required=\"Boolean(required)\"\n spellcheck=\"false\"\n :type=\"inputType\"\n @blur=\"handleBlur\"\n @focus=\"emit('inputFocus')\"\n @update:modelValue=\"(value) => emit('update:modelValue', value)\" />\n </template>\n </div>\n <div\n v-if=\"$slots.warning\"\n class=\"centered-y text-orange absolute right-7 text-xs\">\n <slot name=\"warning\" />\n </div>\n <slot name=\"icon\" />\n <!-- Clear -->\n <ScalarIconButton\n v-if=\"modelValue\"\n class=\"-ml-.25 h-6 w-6 self-center p-1.25\"\n :icon=\"ScalarIconX\"\n label=\"Clear Value\"\n @click=\"emit('update:modelValue', '')\" />\n <!-- Toggle Visibility -->\n <ScalarIconButton\n v-if=\"type === 'password'\"\n class=\"-ml-.5 mr-1.25 h-6 w-6 self-center p-1.25\"\n data-testid=\"data-table-password-toggle\"\n :icon=\"mask ? ScalarIconEye : ScalarIconEyeSlash\"\n :label=\"mask ? 'Show Password' : 'Hide Password'\"\n @click=\"mask = !mask\" />\n </DataTableCell>\n</template>\n\n<style scoped>\n:deep(.cm-editor) {\n padding: 0;\n}\n:deep(.cm-content) {\n align-items: center;\n background-color: transparent;\n display: flex;\n font-family: var(--scalar-font);\n font-size: var(--scalar-small);\n padding: 5px 8px;\n width: 100%;\n}\n:deep(.cm-content):has(.cm-pill) {\n padding: 5px 8px;\n}\n:deep(.cm-content .cm-pill:not(:last-of-type)) {\n margin-right: 0.5px;\n}\n:deep(.cm-content .cm-pill:not(:first-of-type)) {\n margin-left: 0.5px;\n}\n:deep(.cm-line) {\n overflow: hidden;\n padding: 0;\n text-overflow: ellipsis;\n word-break: break-word;\n}\n.required::after {\n content: 'Required';\n}\n/* Tailwind placeholder is busted */\ninput::placeholder {\n color: var(--scalar-color-3);\n}\n/* we want our inputs to look like a password input but not be one */\n.scalar-password-input {\n text-security: disc;\n -webkit-text-security: disc;\n -moz-text-security: disc;\n}\n</style>\n"],"mappings":""}
{"version":3,"file":"DataTableInput.vue.js","names":[],"sources":["../../../../src/v2/components/data-table/DataTableInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarIconButton } from '@scalar/components'\nimport { ScalarIconEye, ScalarIconEyeSlash, ScalarIconX } from '@scalar/icons'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { computed, ref, useTemplateRef } from 'vue'\n\nimport type { VueClassProp } from '@/types/vue'\nimport { CodeInput } from '@/v2/components/code-input'\n\nimport DataTableCell from './DataTableCell.vue'\nimport DataTableInputSelect from './DataTableInputSelect.vue'\n\nconst props = withDefaults(\n defineProps<{\n id?: string\n type?: string | undefined\n /** Class for the wrapping cell because attrs is bound to the input */\n containerClass?: VueClassProp | undefined\n required?: boolean\n modelValue: string\n /** Allows adding a custom value to the enum dropdown, defaults to true */\n canAddCustomEnumValue?: boolean\n readOnly?: boolean\n enum?: string[]\n min?: number\n max?: number\n environment: XScalarEnvironment\n description?: string | undefined\n lineWrapping?: boolean\n /** Whether to show context function suggestions like $guid, $timestamp. Defaults to true */\n withFakeData?: boolean\n }>(),\n {\n canAddCustomEnumValue: true,\n required: false,\n readOnly: false,\n lineWrapping: false,\n withFakeData: true,\n },\n)\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', v: string | number): void\n (e: 'inputFocus'): void\n (e: 'inputBlur'): void\n (e: 'selectVariable', value: string): void\n}>()\n\ndefineOptions({ inheritAttrs: false })\n\nconst mask = ref(true)\nconst interactingWithDropdown = ref(false)\nconst codeInput = useTemplateRef('codeInput')\n\nconst handleBlur = () => !interactingWithDropdown.value && emit('inputBlur')\n\nconst inputType = computed(() =>\n props.type === 'password' ? 'text' : (props.type ?? 'text'),\n)\n\n// If not an enum nor read only, focus the code input\nconst handleLabelClick = () => {\n if (!props.enum?.length && !props.readOnly) {\n codeInput.value?.focus()\n }\n}\n</script>\n<template>\n <DataTableCell\n class=\"relative flex\"\n :class=\"containerClass\">\n <div\n v-if=\"$slots.default\"\n class=\"text-c-1 flex items-center pr-0 pl-3\"\n :for=\"id ?? ''\"\n @click=\"handleLabelClick\">\n <slot />:\n </div>\n <div class=\"relative flex min-w-0 flex-1\">\n <template v-if=\"props.enum && props.enum.length\">\n <DataTableInputSelect\n :canAddCustomValue=\"props.canAddCustomEnumValue\"\n :modelValue=\"props.modelValue\"\n :value=\"props.enum\"\n @update:modelValue=\"emit('update:modelValue', $event)\" />\n </template>\n <template v-else>\n <input\n v-if=\"mask && type === 'password'\"\n v-bind=\"id ? { ...$attrs, id: id } : $attrs\"\n autocomplete=\"off\"\n class=\"text-c-1 disabled:text-c-2 peer w-full min-w-0 border-none px-2 py-1.25 -outline-offset-1\"\n :class=\"{ 'scalar-password-input': type === 'password' }\"\n data-1p-ignore\n :readOnly=\"readOnly\"\n spellcheck=\"false\"\n :type=\"inputType\"\n :value=\"modelValue\"\n @input=\"\n emit(\n 'update:modelValue',\n ($event.target as HTMLInputElement).value ?? '',\n )\n \" />\n <CodeInput\n v-else\n v-bind=\"$attrs\"\n :id=\"id\"\n ref=\"codeInput\"\n class=\"text-c-1 disabled:text-c-2 peer w-full min-w-0 border-none -outline-offset-1\"\n :class=\"[\n type === 'password' && description && 'pr-12',\n description && 'pr-8',\n type === 'password' && 'scalar-password-input',\n ]\"\n :description=\"description\"\n disableCloseBrackets\n disableTabIndent\n :environment=\"environment\"\n :lineWrapping=\"Boolean(lineWrapping)\"\n :max=\"max\"\n :min=\"min\"\n :modelValue=\"modelValue ?? ''\"\n :readOnly=\"readOnly\"\n :required=\"Boolean(required)\"\n spellcheck=\"false\"\n :type=\"inputType\"\n :withFakeData=\"withFakeData\"\n @blur=\"handleBlur\"\n @focus=\"emit('inputFocus')\"\n @update:modelValue=\"(value) => emit('update:modelValue', value)\" />\n </template>\n </div>\n <div\n v-if=\"$slots.warning\"\n class=\"centered-y text-orange absolute right-7 text-xs\">\n <slot name=\"warning\" />\n </div>\n <slot name=\"icon\" />\n <!-- Clear -->\n <ScalarIconButton\n v-if=\"modelValue\"\n class=\"-ml-.25 h-6 w-6 self-center p-1.25\"\n :icon=\"ScalarIconX\"\n label=\"Clear Value\"\n @click=\"emit('update:modelValue', '')\" />\n <!-- Toggle Visibility -->\n <ScalarIconButton\n v-if=\"type === 'password'\"\n class=\"-ml-.5 mr-1.25 h-6 w-6 self-center p-1.25\"\n data-testid=\"data-table-password-toggle\"\n :icon=\"mask ? ScalarIconEye : ScalarIconEyeSlash\"\n :label=\"mask ? 'Show Password' : 'Hide Password'\"\n @click=\"mask = !mask\" />\n </DataTableCell>\n</template>\n\n<style scoped>\n:deep(.cm-editor) {\n padding: 0;\n}\n:deep(.cm-content) {\n align-items: center;\n background-color: transparent;\n display: flex;\n font-family: var(--scalar-font);\n font-size: var(--scalar-small);\n padding: 5px 8px;\n width: 100%;\n}\n:deep(.cm-content):has(.cm-pill) {\n padding: 5px 8px;\n}\n:deep(.cm-content .cm-pill:not(:last-of-type)) {\n margin-right: 0.5px;\n}\n:deep(.cm-content .cm-pill:not(:first-of-type)) {\n margin-left: 0.5px;\n}\n:deep(.cm-line) {\n overflow: hidden;\n padding: 0;\n text-overflow: ellipsis;\n word-break: break-word;\n}\n.required::after {\n content: 'Required';\n}\n/* Tailwind placeholder is busted */\ninput::placeholder {\n color: var(--scalar-color-3);\n}\n/* we want our inputs to look like a password input but not be one */\n.scalar-password-input {\n text-security: disc;\n -webkit-text-security: disc;\n -moz-text-security: disc;\n}\n</style>\n"],"mappings":""}

@@ -47,2 +47,6 @@ import DataTableInputSelect_default from "./DataTableInputSelect.vue.js";

default: false
},
withFakeData: {
type: Boolean,
default: true
}

@@ -119,2 +123,3 @@ },

type: inputType.value,
withFakeData: __props.withFakeData,
onBlur: handleBlur,

@@ -134,3 +139,4 @@ onFocus: _cache[2] || (_cache[2] = ($event) => emit("inputFocus")),

"required",
"type"
"type",
"withFakeData"
]))], 64))]),

@@ -137,0 +143,0 @@ _ctx.$slots.warning ? (openBlock(), createElementBlock("div", _hoisted_4, [renderSlot(_ctx.$slots, "warning", {}, void 0, true)])) : createCommentVNode("", true),

@@ -1,1 +0,1 @@

{"version":3,"file":"DataTableInput.vue.script.js","names":["$slots","$attrs"],"sources":["../../../../src/v2/components/data-table/DataTableInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarIconButton } from '@scalar/components'\nimport { ScalarIconEye, ScalarIconEyeSlash, ScalarIconX } from '@scalar/icons'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { computed, ref, useTemplateRef } from 'vue'\n\nimport type { VueClassProp } from '@/types/vue'\nimport { CodeInput } from '@/v2/components/code-input'\n\nimport DataTableCell from './DataTableCell.vue'\nimport DataTableInputSelect from './DataTableInputSelect.vue'\n\nconst props = withDefaults(\n defineProps<{\n id?: string\n type?: string | undefined\n /** Class for the wrapping cell because attrs is bound to the input */\n containerClass?: VueClassProp | undefined\n required?: boolean\n modelValue: string\n /** Allows adding a custom value to the enum dropdown, defaults to true */\n canAddCustomEnumValue?: boolean\n readOnly?: boolean\n enum?: string[]\n min?: number\n max?: number\n environment: XScalarEnvironment\n description?: string | undefined\n lineWrapping?: boolean\n }>(),\n {\n canAddCustomEnumValue: true,\n required: false,\n readOnly: false,\n lineWrapping: false,\n },\n)\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', v: string | number): void\n (e: 'inputFocus'): void\n (e: 'inputBlur'): void\n (e: 'selectVariable', value: string): void\n}>()\n\ndefineOptions({ inheritAttrs: false })\n\nconst mask = ref(true)\nconst interactingWithDropdown = ref(false)\nconst codeInput = useTemplateRef('codeInput')\n\nconst handleBlur = () => !interactingWithDropdown.value && emit('inputBlur')\n\nconst inputType = computed(() =>\n props.type === 'password' ? 'text' : (props.type ?? 'text'),\n)\n\n// If not an enum nor read only, focus the code input\nconst handleLabelClick = () => {\n if (!props.enum?.length && !props.readOnly) {\n codeInput.value?.focus()\n }\n}\n</script>\n<template>\n <DataTableCell\n class=\"relative flex\"\n :class=\"containerClass\">\n <div\n v-if=\"$slots.default\"\n class=\"text-c-1 flex items-center pr-0 pl-3\"\n :for=\"id ?? ''\"\n @click=\"handleLabelClick\">\n <slot />:\n </div>\n <div class=\"relative flex min-w-0 flex-1\">\n <template v-if=\"props.enum && props.enum.length\">\n <DataTableInputSelect\n :canAddCustomValue=\"props.canAddCustomEnumValue\"\n :modelValue=\"props.modelValue\"\n :value=\"props.enum\"\n @update:modelValue=\"emit('update:modelValue', $event)\" />\n </template>\n <template v-else>\n <input\n v-if=\"mask && type === 'password'\"\n v-bind=\"id ? { ...$attrs, id: id } : $attrs\"\n autocomplete=\"off\"\n class=\"text-c-1 disabled:text-c-2 peer w-full min-w-0 border-none px-2 py-1.25 -outline-offset-1\"\n :class=\"{ 'scalar-password-input': type === 'password' }\"\n data-1p-ignore\n :readOnly=\"readOnly\"\n spellcheck=\"false\"\n :type=\"inputType\"\n :value=\"modelValue\"\n @input=\"\n emit(\n 'update:modelValue',\n ($event.target as HTMLInputElement).value ?? '',\n )\n \" />\n <CodeInput\n v-else\n v-bind=\"$attrs\"\n :id=\"id\"\n ref=\"codeInput\"\n class=\"text-c-1 disabled:text-c-2 peer w-full min-w-0 border-none -outline-offset-1\"\n :class=\"[\n type === 'password' && description && 'pr-12',\n description && 'pr-8',\n type === 'password' && 'scalar-password-input',\n ]\"\n :description=\"description\"\n disableCloseBrackets\n disableTabIndent\n :environment=\"environment\"\n :lineWrapping=\"Boolean(lineWrapping)\"\n :max=\"max\"\n :min=\"min\"\n :modelValue=\"modelValue ?? ''\"\n :readOnly=\"readOnly\"\n :required=\"Boolean(required)\"\n spellcheck=\"false\"\n :type=\"inputType\"\n @blur=\"handleBlur\"\n @focus=\"emit('inputFocus')\"\n @update:modelValue=\"(value) => emit('update:modelValue', value)\" />\n </template>\n </div>\n <div\n v-if=\"$slots.warning\"\n class=\"centered-y text-orange absolute right-7 text-xs\">\n <slot name=\"warning\" />\n </div>\n <slot name=\"icon\" />\n <!-- Clear -->\n <ScalarIconButton\n v-if=\"modelValue\"\n class=\"-ml-.25 h-6 w-6 self-center p-1.25\"\n :icon=\"ScalarIconX\"\n label=\"Clear Value\"\n @click=\"emit('update:modelValue', '')\" />\n <!-- Toggle Visibility -->\n <ScalarIconButton\n v-if=\"type === 'password'\"\n class=\"-ml-.5 mr-1.25 h-6 w-6 self-center p-1.25\"\n data-testid=\"data-table-password-toggle\"\n :icon=\"mask ? ScalarIconEye : ScalarIconEyeSlash\"\n :label=\"mask ? 'Show Password' : 'Hide Password'\"\n @click=\"mask = !mask\" />\n </DataTableCell>\n</template>\n\n<style scoped>\n:deep(.cm-editor) {\n padding: 0;\n}\n:deep(.cm-content) {\n align-items: center;\n background-color: transparent;\n display: flex;\n font-family: var(--scalar-font);\n font-size: var(--scalar-small);\n padding: 5px 8px;\n width: 100%;\n}\n:deep(.cm-content):has(.cm-pill) {\n padding: 5px 8px;\n}\n:deep(.cm-content .cm-pill:not(:last-of-type)) {\n margin-right: 0.5px;\n}\n:deep(.cm-content .cm-pill:not(:first-of-type)) {\n margin-left: 0.5px;\n}\n:deep(.cm-line) {\n overflow: hidden;\n padding: 0;\n text-overflow: ellipsis;\n word-break: break-word;\n}\n.required::after {\n content: 'Required';\n}\n/* Tailwind placeholder is busted */\ninput::placeholder {\n color: var(--scalar-color-3);\n}\n/* we want our inputs to look like a password input but not be one */\n.scalar-password-input {\n text-security: disc;\n -webkit-text-security: disc;\n -moz-text-security: disc;\n}\n</style>\n"],"mappings":"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"}
{"version":3,"file":"DataTableInput.vue.script.js","names":["$slots","$attrs"],"sources":["../../../../src/v2/components/data-table/DataTableInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarIconButton } from '@scalar/components'\nimport { ScalarIconEye, ScalarIconEyeSlash, ScalarIconX } from '@scalar/icons'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { computed, ref, useTemplateRef } from 'vue'\n\nimport type { VueClassProp } from '@/types/vue'\nimport { CodeInput } from '@/v2/components/code-input'\n\nimport DataTableCell from './DataTableCell.vue'\nimport DataTableInputSelect from './DataTableInputSelect.vue'\n\nconst props = withDefaults(\n defineProps<{\n id?: string\n type?: string | undefined\n /** Class for the wrapping cell because attrs is bound to the input */\n containerClass?: VueClassProp | undefined\n required?: boolean\n modelValue: string\n /** Allows adding a custom value to the enum dropdown, defaults to true */\n canAddCustomEnumValue?: boolean\n readOnly?: boolean\n enum?: string[]\n min?: number\n max?: number\n environment: XScalarEnvironment\n description?: string | undefined\n lineWrapping?: boolean\n /** Whether to show context function suggestions like $guid, $timestamp. Defaults to true */\n withFakeData?: boolean\n }>(),\n {\n canAddCustomEnumValue: true,\n required: false,\n readOnly: false,\n lineWrapping: false,\n withFakeData: true,\n },\n)\n\nconst emit = defineEmits<{\n (e: 'update:modelValue', v: string | number): void\n (e: 'inputFocus'): void\n (e: 'inputBlur'): void\n (e: 'selectVariable', value: string): void\n}>()\n\ndefineOptions({ inheritAttrs: false })\n\nconst mask = ref(true)\nconst interactingWithDropdown = ref(false)\nconst codeInput = useTemplateRef('codeInput')\n\nconst handleBlur = () => !interactingWithDropdown.value && emit('inputBlur')\n\nconst inputType = computed(() =>\n props.type === 'password' ? 'text' : (props.type ?? 'text'),\n)\n\n// If not an enum nor read only, focus the code input\nconst handleLabelClick = () => {\n if (!props.enum?.length && !props.readOnly) {\n codeInput.value?.focus()\n }\n}\n</script>\n<template>\n <DataTableCell\n class=\"relative flex\"\n :class=\"containerClass\">\n <div\n v-if=\"$slots.default\"\n class=\"text-c-1 flex items-center pr-0 pl-3\"\n :for=\"id ?? ''\"\n @click=\"handleLabelClick\">\n <slot />:\n </div>\n <div class=\"relative flex min-w-0 flex-1\">\n <template v-if=\"props.enum && props.enum.length\">\n <DataTableInputSelect\n :canAddCustomValue=\"props.canAddCustomEnumValue\"\n :modelValue=\"props.modelValue\"\n :value=\"props.enum\"\n @update:modelValue=\"emit('update:modelValue', $event)\" />\n </template>\n <template v-else>\n <input\n v-if=\"mask && type === 'password'\"\n v-bind=\"id ? { ...$attrs, id: id } : $attrs\"\n autocomplete=\"off\"\n class=\"text-c-1 disabled:text-c-2 peer w-full min-w-0 border-none px-2 py-1.25 -outline-offset-1\"\n :class=\"{ 'scalar-password-input': type === 'password' }\"\n data-1p-ignore\n :readOnly=\"readOnly\"\n spellcheck=\"false\"\n :type=\"inputType\"\n :value=\"modelValue\"\n @input=\"\n emit(\n 'update:modelValue',\n ($event.target as HTMLInputElement).value ?? '',\n )\n \" />\n <CodeInput\n v-else\n v-bind=\"$attrs\"\n :id=\"id\"\n ref=\"codeInput\"\n class=\"text-c-1 disabled:text-c-2 peer w-full min-w-0 border-none -outline-offset-1\"\n :class=\"[\n type === 'password' && description && 'pr-12',\n description && 'pr-8',\n type === 'password' && 'scalar-password-input',\n ]\"\n :description=\"description\"\n disableCloseBrackets\n disableTabIndent\n :environment=\"environment\"\n :lineWrapping=\"Boolean(lineWrapping)\"\n :max=\"max\"\n :min=\"min\"\n :modelValue=\"modelValue ?? ''\"\n :readOnly=\"readOnly\"\n :required=\"Boolean(required)\"\n spellcheck=\"false\"\n :type=\"inputType\"\n :withFakeData=\"withFakeData\"\n @blur=\"handleBlur\"\n @focus=\"emit('inputFocus')\"\n @update:modelValue=\"(value) => emit('update:modelValue', value)\" />\n </template>\n </div>\n <div\n v-if=\"$slots.warning\"\n class=\"centered-y text-orange absolute right-7 text-xs\">\n <slot name=\"warning\" />\n </div>\n <slot name=\"icon\" />\n <!-- Clear -->\n <ScalarIconButton\n v-if=\"modelValue\"\n class=\"-ml-.25 h-6 w-6 self-center p-1.25\"\n :icon=\"ScalarIconX\"\n label=\"Clear Value\"\n @click=\"emit('update:modelValue', '')\" />\n <!-- Toggle Visibility -->\n <ScalarIconButton\n v-if=\"type === 'password'\"\n class=\"-ml-.5 mr-1.25 h-6 w-6 self-center p-1.25\"\n data-testid=\"data-table-password-toggle\"\n :icon=\"mask ? ScalarIconEye : ScalarIconEyeSlash\"\n :label=\"mask ? 'Show Password' : 'Hide Password'\"\n @click=\"mask = !mask\" />\n </DataTableCell>\n</template>\n\n<style scoped>\n:deep(.cm-editor) {\n padding: 0;\n}\n:deep(.cm-content) {\n align-items: center;\n background-color: transparent;\n display: flex;\n font-family: var(--scalar-font);\n font-size: var(--scalar-small);\n padding: 5px 8px;\n width: 100%;\n}\n:deep(.cm-content):has(.cm-pill) {\n padding: 5px 8px;\n}\n:deep(.cm-content .cm-pill:not(:last-of-type)) {\n margin-right: 0.5px;\n}\n:deep(.cm-content .cm-pill:not(:first-of-type)) {\n margin-left: 0.5px;\n}\n:deep(.cm-line) {\n overflow: hidden;\n padding: 0;\n text-overflow: ellipsis;\n word-break: break-word;\n}\n.required::after {\n content: 'Required';\n}\n/* Tailwind placeholder is busted */\ninput::placeholder {\n color: var(--scalar-color-3);\n}\n/* we want our inputs to look like a password input but not be one */\n.scalar-password-input {\n text-security: disc;\n -webkit-text-security: disc;\n -moz-text-security: disc;\n}\n</style>\n"],"mappings":"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"}

@@ -12,7 +12,7 @@ type __VLS_Props = {

declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
cancel: () => any;
submit: () => any;
cancel: () => any;
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
onCancel?: (() => any) | undefined;
onSubmit?: (() => any) | undefined;
onCancel?: (() => any) | undefined;
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;

@@ -19,0 +19,0 @@ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;

//#region src/v2/constants.ts
/** The version number taken from the package.json. Consumers can override at build time via define (e.g. OVERRIDE_PACKAGE_VERSION: JSON.stringify('1.2.3')). */
var APP_VERSION = typeof OVERRIDE_PACKAGE_VERSION !== "undefined" ? OVERRIDE_PACKAGE_VERSION : "3.1.0";
var APP_VERSION = typeof OVERRIDE_PACKAGE_VERSION !== "undefined" ? OVERRIDE_PACKAGE_VERSION : "3.2.0";
//#endregion

@@ -5,0 +5,0 @@ export { APP_VERSION };

@@ -7,2 +7,3 @@ import type { ScalarListboxOption, WorkspaceGroup } from '@scalar/components';

import { type WorkspaceStore } from '@scalar/workspace-store/client';
import type { ApiClientAppOptions } from '../../../v2/features/app/helpers/create-api-client-app.js';
import { type WorkspaceEventBus } from '@scalar/workspace-store/events';

@@ -97,2 +98,4 @@ import type { WorkspaceDocument } from '@scalar/workspace-store/schemas';

loading: Ref<boolean>;
/** Runtime behaviour overrides */
options?: ApiClientAppOptions;
/** The currently active entities */

@@ -137,3 +140,3 @@ activeEntities: {

};
export declare const createAppState: ({ router, fileLoader, fallbackThemeSlug, customThemes, telemetryDefault, }: {
export declare const createAppState: ({ router, fileLoader, fallbackThemeSlug, customThemes, telemetryDefault, options, }: {
router: Router;

@@ -144,4 +147,6 @@ fileLoader?: LoaderPlugin;

telemetryDefault?: boolean;
/** Runtime behaviour overrides */
options?: ApiClientAppOptions;
}) => Promise<AppState>;
export {};
//# sourceMappingURL=app-state.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"app-state.d.ts","sourceRoot":"","sources":["../../../../src/v2/features/app/app-state.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"app-state.d.ts","sourceRoot":"","sources":["../../../../src/v2/features/app/app-state.ts"],"names":[],"mappings":"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"}

@@ -27,3 +27,3 @@ import { slugify } from "../../helpers/slugify.js";

var DEFAULT_SIDEBAR_WIDTH = 288;
var createAppState = async ({ router, fileLoader, fallbackThemeSlug = () => "default", customThemes = () => [], telemetryDefault }) => {
var createAppState = async ({ router, fileLoader, fallbackThemeSlug = () => "default", customThemes = () => [], telemetryDefault, options }) => {
/** Workspace event bus for handling workspace-level events. */

@@ -107,3 +107,4 @@ const eventBus = createWorkspaceEventBus({ debug: false });

})],
fileLoader
fileLoader,
fetch: options?.customFetch
});

@@ -625,3 +626,4 @@ };

},
telemetry
telemetry,
options
};

@@ -628,0 +630,0 @@ };

@@ -1,1 +0,1 @@

{"version":3,"file":"app-state.js","names":[],"sources":["../../../../src/v2/features/app/app-state.ts"],"sourcesContent":["import type { ScalarListboxOption, WorkspaceGroup } from '@scalar/components'\nimport { isDefined } from '@scalar/helpers/array/is-defined'\nimport { sortByOrder } from '@scalar/helpers/array/sort-by-order'\nimport type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport type { LoaderPlugin } from '@scalar/json-magic/bundle'\nimport { migrateLocalStorageToIndexDb } from '@scalar/oas-utils/migrations'\nimport { createSidebarState, generateReverseIndex } from '@scalar/sidebar'\nimport type { Theme } from '@scalar/themes'\nimport { type WorkspaceStore, createWorkspaceStore } from '@scalar/workspace-store/client'\nimport {\n type OperationExampleMeta,\n type WorkspaceEventBus,\n createWorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport { generateUniqueValue } from '@scalar/workspace-store/helpers/generate-unique-value'\nimport { getParentEntry } from '@scalar/workspace-store/navigation'\nimport { createWorkspaceStorePersistence, getWorkspaceId } from '@scalar/workspace-store/persistence'\nimport { persistencePlugin } from '@scalar/workspace-store/plugins/client'\nimport { getActiveEnvironment } from '@scalar/workspace-store/request-example'\nimport type { Workspace, WorkspaceDocument } from '@scalar/workspace-store/schemas'\nimport { extensions } from '@scalar/workspace-store/schemas/extensions'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { Tab } from '@scalar/workspace-store/schemas/extensions/workspace/x-scalar-tabs'\nimport type { TraversedEntry } from '@scalar/workspace-store/schemas/navigation'\nimport {\n type ComputedRef,\n type MaybeRefOrGetter,\n type Ref,\n type ShallowRef,\n computed,\n readonly,\n ref,\n shallowRef,\n watch,\n} from 'vue'\nimport type { RouteLocationNormalizedGeneric, RouteLocationRaw, Router } from 'vue-router'\n\nimport { getRouteParam } from '@/v2/features/app/helpers/get-route-param'\nimport { groupWorkspacesByTeam } from '@/v2/features/app/helpers/group-workspaces'\nimport { useTheme } from '@/v2/features/app/hooks/use-theme'\nimport { getTabDetails } from '@/v2/helpers/get-tab-details'\nimport { slugify } from '@/v2/helpers/slugify'\nimport { workspaceStorage } from '@/v2/helpers/storage'\n\nimport { initializeAppEventHandlers } from './app-events'\nimport { canLoadWorkspace, filterWorkspacesByTeam } from './helpers/filter-workspaces'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\nexport type GetEntryByLocation = (location: {\n document: string\n path?: string\n method?: HttpMethod\n example?: string\n}) =>\n | (TraversedEntry & {\n parent?: TraversedEntry | undefined\n })\n | undefined\n\ntype WorkspaceOption = ScalarListboxOption & { teamUid: string; namespace: string; slug: string }\n\n/** Defines the overall application state structure and its main feature modules */\nexport type AppState = {\n /** The workspace store */\n store: ShallowRef<WorkspaceStore | null>\n /** The sidebar management */\n sidebar: {\n /** The sidebar state */\n state: ReturnType<typeof createSidebarState<TraversedEntry>>\n /** The width of the sidebar */\n width: ComputedRef<number>\n /** Whether the sidebar is open */\n isOpen: Ref<boolean>\n /** Handles the selection of an item in the sidebar */\n handleSelectItem: (id: string) => void\n /** Handles the width update of the sidebar */\n handleSidebarWidthUpdate: (width: number) => void\n /** Gets the entry by location */\n getEntryByLocation: GetEntryByLocation\n }\n /** The tabs management */\n tabs: {\n /** The tabs state */\n state: Ref<Tab[]>\n /** The active tab index */\n activeTabIndex: Ref<number>\n /** Copies the URL of the tab at the given index to the clipboard */\n copyTabUrl: (index: number) => Promise<void>\n }\n /** The workspace management */\n workspace: {\n /** Creates a new workspace and navigates to it */\n create: (payload: {\n teamUid?: string\n namespace?: string\n slug?: string\n name: string\n }) => Promise<{ name: string; namespace: string; slug: string; teamUid: string } | undefined>\n /** All workspace list */\n workspaceList: Ref<WorkspaceOption[]>\n /** Filtered workspace list, based on the current teamUid */\n filteredWorkspaceList: ComputedRef<WorkspaceOption[]>\n /**\n * Groups workspaces into team and local categories for display in the workspace picker.\n * Team workspaces are shown first (when not on local team), followed by local workspaces.\n */\n workspaceGroups: ComputedRef<WorkspaceGroup[]>\n /** The currently active workspace */\n activeWorkspace: ShallowRef<{ id: string; label: string } | null>\n /** Navigates to the specified workspace */\n navigateToWorkspace: (namespace?: string, slug?: string) => Promise<void>\n /** Whether the workspace page is open */\n isOpen: ComputedRef<boolean>\n }\n /** The workspace event bus for handling workspace-level events */\n eventBus: WorkspaceEventBus\n /** The router instance */\n router: Router\n /** The current route derived from the router */\n currentRoute: Ref<RouteLocationNormalizedGeneric | null>\n /** Whether the workspace is currently syncing */\n loading: Ref<boolean>\n /** The currently active entities */\n activeEntities: {\n /** The namespace of the current entity, e.g. \"default\" or a custom namespace */\n namespace: Ref<string | undefined>\n /** The slug identifying the current workspace */\n workspaceSlug: Ref<string | undefined>\n /** The slug of the currently selected document in the workspace */\n documentSlug: Ref<string | undefined>\n /** The API path currently selected (e.g. \"/users/{id}\") */\n path: Ref<string | undefined>\n /** The HTTP method for the currently selected API path (e.g. GET, POST) */\n method: Ref<HttpMethod | undefined>\n /** The name of the currently selected example (for examples within an endpoint) */\n exampleName: Ref<string | undefined>\n /** The unique identifier for the selected team context (read-only; use setTeamUid to change) */\n teamUid: Readonly<Ref<string>>\n /** Sets the current team context by team UID */\n setTeamUid: (value: string) => void\n }\n /** The currently active environment */\n environment: ComputedRef<XScalarEnvironment>\n /** The currently active document */\n document: ComputedRef<WorkspaceDocument | null>\n /** Whether the current color mode is dark */\n isDarkMode: ComputedRef<boolean>\n /** The currently active theme */\n theme: {\n /** The computed CSS styles for the current theme, as a string */\n styles: ComputedRef<{ themeStyles: string; themeSlug: string }>\n /** The computed value for the <style> tag containing the current theme styles */\n themeStyleTag: ComputedRef<string>\n /** The custom themes to use */\n customThemes: MaybeRefOrGetter<Theme[]>\n }\n telemetry: Ref<boolean>\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n/** Default debounce delay in milliseconds for workspace store persistence. */\nconst DEFAULT_DEBOUNCE_DELAY = 1000\n/** Default sidebar width in pixels. */\nconst DEFAULT_SIDEBAR_WIDTH = 288\n\n// ---------------------------------------------------------------------------\n// App State\n// ---------------------------------------------------------------------------\nexport const createAppState = async ({\n router,\n fileLoader,\n fallbackThemeSlug = () => 'default',\n customThemes = () => [],\n telemetryDefault,\n}: {\n router: Router\n fileLoader?: LoaderPlugin\n customThemes?: MaybeRefOrGetter<Theme[]>\n fallbackThemeSlug?: MaybeRefOrGetter<string>\n telemetryDefault?: boolean\n}): Promise<AppState> => {\n /** Workspace event bus for handling workspace-level events. */\n const eventBus = createWorkspaceEventBus({\n debug: import.meta.env.DEV,\n })\n\n const { workspace: persistence } = await createWorkspaceStorePersistence()\n\n /**\n * Run migration from localStorage to IndexedDB if needed\n * This happens once per user and transforms old data structure to new workspace format\n */\n await migrateLocalStorageToIndexDb()\n\n // ---------------------------------------------------------------------------\n // Active entities\n // ---------------------------------------------------------------------------\n const teamUid = ref<string>('local')\n const namespace = ref<string | undefined>(undefined)\n const workspaceSlug = ref<string | undefined>(undefined)\n const documentSlug = ref<string | undefined>(undefined)\n const method = ref<HttpMethod | undefined>(undefined)\n const path = ref<string | undefined>(undefined)\n const exampleName = ref<string | undefined>(undefined)\n\n // ---------------------------------------------------------------------------\n // Loading states\n const isSyncingWorkspace = ref(false)\n\n // ---------------------------------------------------------------------------\n // Router state\n router.afterEach((to) => handleRouteChange(to))\n const currentRoute = computed(() => router.currentRoute.value ?? null)\n\n // ---------------------------------------------------------------------------\n // Workspace persistence state management\n const activeWorkspace = shallowRef<{ id: string; label: string } | null>(null)\n const workspaces = ref<WorkspaceOption[]>([])\n const filteredWorkspaces = computed(() => filterWorkspacesByTeam(workspaces.value, teamUid.value))\n const workspaceGroups = computed(() => groupWorkspacesByTeam(filteredWorkspaces.value, teamUid.value))\n const store = shallowRef<WorkspaceStore | null>(null)\n\n // Load persisted telemetry preference, falling back to the provided default\n const persistedTelemetry = workspaceStorage.getTelemetry()\n const telemetry = ref(persistedTelemetry !== null ? persistedTelemetry : Boolean(telemetryDefault))\n watch(telemetry, (value) => workspaceStorage.setTelemetry(value))\n\n const activeDocument = computed(() => {\n return store.value?.workspace.documents[documentSlug.value ?? ''] || null\n })\n\n /**\n * Merged environment variables from workspace and document levels.\n * Variables from both sources are combined, with document variables\n * taking precedence in case of naming conflicts.\n */\n const environment = computed<XScalarEnvironment>(\n () => getActiveEnvironment(store.value, activeDocument.value).environment,\n )\n\n /** Update the workspace list when the component is mounted */\n workspaces.value = await persistence.getAll().then((w) =>\n w.map(({ teamUid, namespace, slug, name }) => ({\n id: getWorkspaceId(namespace, slug),\n teamUid,\n namespace,\n slug,\n label: name,\n })),\n )\n\n /**\n * Renames the currently active workspace.\n * Updates the workspace name in persistence and updates activeWorkspace if successful.\n * Returns early if namespace or workspaceSlug is not set, or if update fails.\n */\n const renameWorkspace = async (name: string) => {\n const namespaceValue = namespace.value\n const slugValue = workspaceSlug.value\n if (!namespaceValue || !slugValue) {\n return\n }\n const workspaceId = getWorkspaceId(namespaceValue, slugValue)\n const updateResult = await persistence.updateName({ namespace: namespaceValue, slug: slugValue }, name)\n\n // If the update fails, return early\n if (updateResult === undefined) {\n return\n }\n\n // Update the workspace list\n workspaces.value = workspaces.value.map((workspace) => {\n // If the workspace is the currently active workspace, update the label\n if (workspace.id === workspaceId) {\n return { ...workspace, label: name }\n }\n return workspace\n })\n activeWorkspace.value = { id: workspaceId, label: name }\n }\n\n /**\n * Creates a client-side workspace store with persistence enabled for the given workspace id.\n */\n const createClientStore = async ({\n namespace,\n slug,\n }: {\n namespace: string\n slug: string\n }): Promise<WorkspaceStore> => {\n return createWorkspaceStore({\n plugins: [\n await persistencePlugin({\n workspaceId: getWorkspaceId(namespace, slug),\n debounceDelay: DEFAULT_DEBOUNCE_DELAY,\n }),\n ],\n fileLoader,\n })\n }\n\n /**\n * Attempts to load and activate a workspace by id.\n * Returns true when the workspace was found and activated.\n */\n const loadWorkspace = async (\n namespace: string,\n slug: string,\n ): Promise<{ success: true; workspace: Workspace } | { success: false }> => {\n const workspace = await persistence.getItem({ namespace, slug })\n\n if (!workspace) {\n return {\n success: false,\n }\n }\n\n const client = await createClientStore({ namespace, slug })\n client.loadWorkspace(workspace.workspace)\n activeWorkspace.value = { id: getWorkspaceId(workspace.namespace, workspace.slug), label: workspace.name }\n store.value = client\n\n return {\n success: true,\n workspace: client.workspace,\n }\n }\n\n /**\n * Creates and persists the default workspace with a blank draft document.\n * Used when no workspaces exist yet.\n */\n const createAndPersistWorkspace = async ({\n name,\n teamUid,\n namespace,\n slug,\n }: {\n name: string\n teamUid?: string\n namespace?: string\n slug: string\n }) => {\n const draftStore = createWorkspaceStore()\n await draftStore.addDocument({\n name: 'drafts',\n document: {\n openapi: '3.1.0',\n info: {\n title: 'Drafts',\n version: '1.0.0',\n },\n paths: {\n '/': {\n get: {},\n },\n },\n 'x-scalar-original-document-hash': 'drafts',\n 'x-scalar-icon': 'interface-edit-tool-pencil',\n },\n })\n\n // Persist the workspace\n const workspace = await persistence.setItem(\n { namespace, slug },\n {\n name: name,\n teamUid,\n workspace: draftStore.exportWorkspace(),\n },\n )\n\n // Update the workspace list\n workspaces.value.push({\n id: getWorkspaceId(workspace.namespace, workspace.slug),\n teamUid: workspace.teamUid,\n namespace: workspace.namespace,\n slug: workspace.slug,\n label: workspace.name,\n })\n return workspace\n }\n\n /**\n * Navigates to the overview page of the specified workspace.\n *\n * @param namespace - The workspace namespace.\n * @param slug - The unique workspace slug (identifier).\n */\n const navigateToWorkspace = async (namespace?: string, slug?: string): Promise<void> => {\n if (!namespace || !slug) {\n await router.push('/')\n return\n }\n\n // We should always have this drafts document available in a new workspace\n await router.push({\n name: 'example',\n params: {\n namespace,\n workspaceSlug: slug,\n documentSlug: 'drafts',\n pathEncoded: encodeURIComponent('/'),\n method: 'get',\n exampleName: 'default',\n },\n })\n }\n\n /**\n * Creates a new workspace with the provided name.\n * - Generates a unique slug for the workspace (uses the provided slug if it is unique, otherwise generates a unique slug).\n * - Adds a default blank document (\"drafts\") to the workspace.\n * - Persists the workspace and navigates to it.\n *\n * Example usage:\n * await createWorkspace({ name: 'My Awesome API' })\n * // -> Navigates to /workspace/my-awesome-api (if available)\n */\n const createWorkspace = async ({\n teamUid,\n namespace,\n slug,\n name,\n }: {\n teamUid?: string\n namespace?: string\n slug?: string\n name: string\n }) => {\n // Clear up the current store, in order to show the loading state\n store.value = null\n\n // Generate a unique slug/id for the workspace, based on the name.\n const newWorkspaceSlug = await generateUniqueValue({\n defaultValue: slug ?? name, // Use the provided id if it exists, otherwise use the name\n validation: async (value) => !(await persistence.has({ namespace: namespace ?? 'local', slug: value })),\n maxRetries: 100,\n transformation: slugify,\n })\n\n // Failed to generate a unique workspace id, so we can't create the workspace.\n if (!newWorkspaceSlug) {\n return undefined\n }\n\n const newWorkspaceDetails = {\n teamUid,\n namespace,\n slug: newWorkspaceSlug,\n name,\n }\n\n // Create a new client store with the workspace ID and add a default document.\n const createdWorkspace = await createAndPersistWorkspace(newWorkspaceDetails)\n\n // Navigate to the newly created workspace.\n await navigateToWorkspace(createdWorkspace.namespace, createdWorkspace.slug)\n return createdWorkspace\n }\n\n /**\n * Handles changing the active workspace when the workspace slug changes in the route.\n * This function:\n * - Clears the current workspace store and sets loading state.\n * - Attempts to load the workspace by slug.\n * - If found, navigates to the active tab path (if available).\n * - If not found, creates the default workspace and navigates to it.\n */\n const changeWorkspace = async (namespace: string, slug: string) => {\n // Clear the current store and set loading to true before loading new workspace.\n store.value = null\n isSyncingWorkspace.value = true\n\n // Try to load the workspace\n const result = await loadWorkspace(namespace, slug)\n\n if (result.success) {\n // Navigate to the correct tab if the workspace has a tab already\n const index = result.workspace['x-scalar-active-tab'] ?? 0\n const tabs = result.workspace['x-scalar-tabs']\n const tab = tabs?.[index]\n\n if (tab) {\n // Preserve query parameters when navigating to the active tab\n await router.replace({\n path: tab.path,\n query: currentRoute.value?.query ?? {},\n })\n }\n\n // Heal the active tab index if it is out of bounds\n if (tabs && index >= tabs.length) {\n eventBus.emit('tabs:update:tabs', {\n 'x-scalar-active-tab': 0,\n })\n }\n\n // Initialize the tabs if they does not exist\n if (!tabs) {\n eventBus.emit('tabs:update:tabs', {\n 'x-scalar-tabs': [createTabFromRoute(currentRoute.value)],\n 'x-scalar-active-tab': 0,\n })\n }\n\n isSyncingWorkspace.value = false\n return\n }\n\n // Navigate to the default workspace, or fall back to the first available workspace\n const targetWorkspace =\n filteredWorkspaces.value.find((workspace) => workspace.teamUid === 'local' && workspace.slug === 'default') ??\n filteredWorkspaces.value[0]\n\n if (targetWorkspace) {\n return navigateToWorkspace(targetWorkspace.namespace, targetWorkspace.slug)\n }\n\n // If loading failed (workspace does not exist), create the default workspace and navigate to it.\n const createResult = await createWorkspace({\n name: 'Default Workspace',\n slug: 'default',\n })\n\n isSyncingWorkspace.value = false\n\n if (!createResult) {\n return console.error('Failed to create the default workspace, something went wrong, can not load the workspace')\n }\n\n // Must reset the sidebar state when the workspace changes\n sidebarState.reset()\n }\n\n /**\n * Sets the current team context. If the active workspace is not accessible\n * with the new team, navigates to the default workspace for that team.\n */\n const setTeamUid = (value: string) => {\n // Update the new teamUid\n teamUid.value = value\n\n // Find the current workspace\n const workspace = filteredWorkspaces.value.find(\n (w) => w.namespace === namespace.value && w.slug === workspaceSlug.value,\n )\n\n // Check if new teamUid is accessible to the current workspace\n if (workspace && canLoadWorkspace(workspace.teamUid, value)) {\n return\n }\n\n return navigateToWorkspace('local', 'default')\n }\n\n // ---------------------------------------------------------------------------\n // Sidebar state management\n\n const entries = computed(() => {\n const activeStore = store.value\n if (!activeStore) {\n return []\n }\n\n const order = activeStore.workspace['x-scalar-order'] ?? Object.keys(activeStore.workspace.documents)\n\n return sortByOrder(Object.keys(activeStore.workspace.documents), order, (item) => item)\n .map((doc) => activeStore.workspace.documents[doc]?.['x-scalar-navigation'])\n .filter(isDefined) as TraversedEntry[]\n })\n\n const sidebarState = createSidebarState(entries)\n\n /**\n * Generates a unique string ID for an API location, based on the document, path, method, and example.\n * Filters out undefined values and serializes the composite array into a stable string.\n *\n * @param params - An object containing document, path, method, and optional example name.\n * @returns A stringified array representing the unique location identifier.\n *\n * Example:\n * generateId({ document: 'mydoc', path: '/users', method: 'get', example: 'default' })\n * // => '[\"mydoc\",\"/users\",\"get\",\"default\"]'\n */\n const generateId = ({\n document,\n path,\n method,\n example,\n }: {\n document: string\n path?: string\n method?: HttpMethod\n example?: string\n }) => {\n return JSON.stringify([document, path, method, example].filter(isDefined))\n }\n\n /**\n * Computed index for fast lookup of sidebar nodes by their unique API location.\n *\n * - Only indexes nodes of type 'document', 'operation', or 'example'.\n * - The lookup key is a serialized array of: [documentName, operationPath, operationMethod, exampleName?].\n * - Supports precise resolution of sidebar entries given an API \"location\".\n */\n const locationIndex = computed(() =>\n generateReverseIndex({\n items: entries.value,\n nestedKey: 'children',\n filter: (node) => node.type === 'document' || node.type === 'operation' || node.type === 'example',\n getId: (node) => {\n const document = getParentEntry('document', node)\n const operation = getParentEntry('operation', node)\n return generateId({\n document: document?.name ?? '',\n path: operation?.path,\n method: operation?.method,\n example: node.type === 'example' ? node.name : undefined,\n })\n },\n }),\n )\n\n /**\n * Looks up a sidebar entry by its unique API location.\n * - First tries to find an entry matching all provided properties (including example).\n * - If not found, falls back to matching only the operation (ignores example field).\n * This allows resolving either examples, operations, or documents as appropriate.\n *\n * @param location - Object specifying the document name, path, method, and optional example name.\n * @returns The matching sidebar entry, or undefined if none found.\n *\n * Example:\n * const entry = getEntryByLocation({\n * document: 'pets',\n * path: '/pets',\n * method: 'get',\n * example: 'default',\n * })\n */\n const getEntryByLocation: GetEntryByLocation = (location) => {\n // Try to find an entry with the most-specific location (including example)\n const entryWithExample = locationIndex.value.get(generateId(location))\n\n if (entryWithExample) {\n return entryWithExample\n }\n\n // Fallback to the operation (ignoring example) if an example wasn't found or specified\n return locationIndex.value.get(\n generateId({\n document: location.document,\n path: location.path,\n method: location.method,\n }),\n )\n }\n\n /**\n * Handles item selection from the sidebar and routes navigation accordingly.\n *\n * Example:\n * handleSelectItem('id-of-entry')\n */\n const handleSelectItem = (id: string) => {\n const entry = sidebarState.getEntryById(id)\n\n if (!entry) {\n console.warn(`Could not find sidebar entry with id ${id} to select`)\n return\n }\n\n /** Close sidebar and navigate. Used for every branch that performs navigation. */\n const navigate = (route: RouteLocationRaw) => {\n isSidebarOpen.value = false\n return router.push(route)\n }\n\n // Navigate to the document overview page\n if (entry.type === 'document') {\n // If we are already in the document, just toggle expansion\n if (sidebarState.selectedItem.value === id) {\n sidebarState.setExpanded(id, !sidebarState.isExpanded(id))\n return\n }\n\n // Otherwise, select it\n sidebarState.setSelected(id)\n sidebarState.setExpanded(id, true)\n return navigate({\n name: 'document.overview',\n params: { documentSlug: entry.name },\n })\n }\n\n // Navigate to the example page\n if (entry.type === 'operation') {\n // If we are already in an operation child we just want to toggle the explanstion\n if (sidebarState.isSelected(id) && sidebarState.selectedItem.value !== id) {\n sidebarState.setExpanded(id, !sidebarState.isExpanded(id))\n return\n }\n\n // Otherwise, select the first example\n const firstExample = entry.children?.find((child) => child.type === 'example')\n\n if (firstExample) {\n sidebarState.setSelected(firstExample.id)\n sidebarState.setExpanded(firstExample.id, true)\n } else {\n sidebarState.setSelected(id)\n }\n\n return navigate({\n name: 'example',\n params: {\n documentSlug: getParentEntry('document', entry)?.name,\n pathEncoded: encodeURIComponent(entry.path),\n method: entry.method,\n exampleName: firstExample?.name ?? 'default',\n },\n })\n }\n\n // Navigate to the example page\n if (entry.type === 'example') {\n sidebarState.setSelected(id)\n const operation = getParentEntry('operation', entry)\n return navigate({\n name: 'example',\n params: {\n documentSlug: getParentEntry('document', entry)?.name,\n pathEncoded: encodeURIComponent(operation?.path ?? ''),\n method: operation?.method,\n exampleName: entry.name,\n },\n })\n }\n\n if (entry.type === 'text') {\n return navigate({\n name: 'document.overview',\n params: {\n documentSlug: getParentEntry('document', entry)?.name,\n },\n })\n }\n\n sidebarState.setExpanded(id, !sidebarState.isExpanded(id))\n return\n }\n\n /**\n * Navigates to the currently active tab's path using the router.\n * Returns early if the workspace store or active tab is unavailable.\n */\n const navigateToCurrentTab = async (): Promise<void> => {\n if (!store.value) {\n return\n }\n\n const activeTabIndex = store.value.workspace['x-scalar-active-tab'] ?? 0\n const activeTab = store.value.workspace['x-scalar-tabs']?.[activeTabIndex]\n if (!activeTab) {\n return\n }\n\n await router.replace(activeTab.path)\n }\n\n /**\n * Rebuilds the sidebar for the given document.\n * This is used to refresh the sidebar state after structural changes (e.g. after adding or removing items).\n *\n * @param documentName - The name (id) of the document for which to rebuild the sidebar\n */\n const rebuildSidebar = (documentName: string | undefined) => {\n if (documentName) {\n store.value?.buildSidebar(documentName)\n }\n }\n\n /**\n * Ensures the sidebar is refreshed after a new example is created.\n *\n * If the sidebar entry for the new example does not exist or is of a different type,\n * this will rebuild the sidebar for the current document. This helps keep the sidebar state\n * consistent (e.g., after adding a new example via the UI).\n */\n const refreshSidebarAfterExampleCreation = (payload: OperationExampleMeta & { documentName?: string }) => {\n const documentName = payload.documentName ?? activeDocument.value?.['x-scalar-navigation']?.name\n if (!documentName) {\n return\n }\n\n const entry = getEntryByLocation({\n document: documentName,\n path: payload.path,\n method: payload.method,\n example: payload.exampleKey,\n })\n\n if (!entry || entry.type !== 'example') {\n // Sidebar entry for this example doesn't exist, so rebuild sidebar for consistency.\n rebuildSidebar(documentName)\n if (currentRoute.value) {\n syncSidebar(currentRoute.value)\n }\n }\n return\n }\n\n /** Width of the sidebar, with fallback to default. */\n const sidebarWidth = computed(() => store.value?.workspace?.['x-scalar-sidebar-width'] ?? DEFAULT_SIDEBAR_WIDTH)\n\n /** Handler for sidebar width changes. */\n const handleSidebarWidthUpdate = (width: number) => store.value?.update('x-scalar-sidebar-width', width)\n\n /** Controls the visibility of the sidebar. */\n const isSidebarOpen = ref(false)\n // ---------------------------------------------------------------------------\n // Tab Management\n\n /** Constants for workspace store keys */\n const TABS_KEY = 'x-scalar-tabs' as const\n const ACTIVE_TAB_KEY = 'x-scalar-active-tab' as const\n\n /**\n * Creates a tab object based on the current route and workspace state.\n * Used as a fallback when no tabs exist or when creating new tabs.\n */\n const createTabFromRoute = (to: RouteLocationNormalizedGeneric | null): Tab => {\n const method = getRouteParam('method', to)\n const path = getRouteParam('pathEncoded', to)\n const document = getRouteParam('documentSlug', to)\n const workspace = getRouteParam('workspaceSlug', to)\n return {\n ...getTabDetails({\n workspace,\n document,\n path,\n method,\n getEntryByLocation,\n }),\n path: currentRoute.value?.path ?? '',\n }\n }\n\n const tabs = computed(() => {\n return store.value?.workspace[TABS_KEY] ?? [createTabFromRoute(currentRoute.value)]\n })\n\n const activeTabIndex = computed(() => {\n return store.value?.workspace[ACTIVE_TAB_KEY] ?? 0\n })\n\n /**\n * Copies the URL of the tab at the given index to the clipboard.\n * Constructs the full URL using the current origin and the tab path.\n *\n * Note: Will silently fail if clipboard API is unavailable or the tab does not exist.\n */\n const copyTabUrl = async (index: number): Promise<void> => {\n const tab = tabs.value[index]\n\n if (!tab) {\n console.warn(`Cannot copy URL: tab at index ${index} does not exist`)\n return\n }\n\n const url = `${window.location.origin}${tab.path}`\n\n try {\n await navigator.clipboard.writeText(url)\n } catch (error) {\n console.error('Failed to copy URL to clipboard:', error)\n }\n }\n\n // ---------------------------------------------------------------------------\n // Path syncing\n\n /** When the route changes we need to update the active entities in the store */\n const handleRouteChange = (to: RouteLocationNormalizedGeneric) => {\n const slug = getRouteParam('workspaceSlug', to)\n const document = getRouteParam('documentSlug', to)\n const namespaceValue = getRouteParam('namespace', to)\n\n // Must have an active workspace to syncs\n if (!namespaceValue || !slug) {\n return\n }\n\n // Try to see if the user can load this workspace based on the teamUid and namespace\n const workspace = workspaces.value.find(\n (workspace) => workspace.slug === slug && workspace.namespace === namespaceValue,\n )\n\n // If the workspace is not found or the teamUid does not match, try to redirect to the default workspace\n if (workspace && !canLoadWorkspace(workspace.teamUid, teamUid.value)) {\n // try to redirect to the default workspace\n return navigateToWorkspace('local', 'default')\n }\n\n namespace.value = namespaceValue\n workspaceSlug.value = slug\n documentSlug.value = document\n method.value = getRouteParam('method', to)\n path.value = getRouteParam('pathEncoded', to)\n exampleName.value = getRouteParam('exampleName', to)\n\n // Save the current path to the persistence storage\n if (to.path !== '') {\n workspaceStorage.setCurrentPath(to.path)\n }\n\n if (getWorkspaceId(namespace.value, slug) !== activeWorkspace.value?.id) {\n return changeWorkspace(namespace.value, slug)\n }\n\n // Update the active document if the document slug has changes\n if (document && document !== store.value?.workspace[extensions.workspace.activeDocument]) {\n store?.value?.update('x-scalar-active-document', document)\n }\n\n syncTabs(to)\n syncSidebar(to)\n return\n }\n\n /** Aligns the tabs with any potential slug changes */\n const syncTabs = (to: RouteLocationNormalizedGeneric) => {\n const tabs = store.value?.workspace['x-scalar-tabs'] ?? []\n const index = store.value?.workspace['x-scalar-active-tab'] ?? 0\n\n const tab = tabs[index]\n\n // If there is no tab or the tab path is the same we leave the tab state alone\n if (!tab || tab.path === to.path) {\n // Already on the correct path, do nothing\n return\n }\n\n // Otherwise we replace the tab content with the new route\n tabs[index] = createTabFromRoute(to)\n }\n\n /** Aligns the sidebar state with any potential slug changes */\n const syncSidebar = (to: RouteLocationNormalizedGeneric) => {\n const document = getRouteParam('documentSlug', to)\n\n if (!document) {\n // Reset selection if no document is selected\n sidebarState.setSelected(null)\n return\n }\n\n const entry = getEntryByLocation({\n document,\n path: getRouteParam('pathEncoded', to),\n method: getRouteParam('method', to),\n example: getRouteParam('exampleName', to),\n })\n\n if (entry) {\n sidebarState.setSelected(entry.id)\n sidebarState.setExpanded(entry.id, true)\n }\n }\n\n // ---------------------------------------------------------------------------\n // Events handling\n\n initializeAppEventHandlers({\n eventBus,\n router,\n store,\n navigateToCurrentTab,\n rebuildSidebar,\n onAfterExampleCreation: refreshSidebarAfterExampleCreation,\n onSelectSidebarItem: handleSelectItem,\n onCopyTabUrl: (index) => copyTabUrl(index),\n onToggleSidebar: () => (isSidebarOpen.value = !isSidebarOpen.value),\n closeSidebar: () => (isSidebarOpen.value = false),\n renameWorkspace,\n })\n\n const theme = useTheme({\n fallbackThemeSlug,\n customThemes,\n store: store,\n })\n\n const isDarkMode = computed(() => {\n const colorMode = store.value?.workspace['x-scalar-color-mode'] ?? 'system'\n if (colorMode === 'system') {\n return window.matchMedia?.('(prefers-color-scheme: dark)')?.matches ?? false\n }\n return colorMode === 'dark'\n })\n\n return {\n /** Active workspace store */\n store,\n sidebar: {\n state: sidebarState,\n width: sidebarWidth,\n isOpen: isSidebarOpen,\n handleSelectItem,\n handleSidebarWidthUpdate,\n getEntryByLocation,\n },\n tabs: {\n state: tabs,\n activeTabIndex,\n copyTabUrl,\n },\n workspace: {\n create: createWorkspace,\n workspaceList: workspaces,\n filteredWorkspaceList: filteredWorkspaces,\n workspaceGroups,\n activeWorkspace,\n navigateToWorkspace,\n isOpen: computed(() => Boolean(workspaceSlug.value && !documentSlug.value)),\n },\n eventBus,\n router,\n currentRoute,\n loading: isSyncingWorkspace,\n activeEntities: {\n namespace,\n workspaceSlug,\n documentSlug,\n path,\n method,\n exampleName,\n teamUid: readonly(teamUid),\n setTeamUid,\n },\n environment,\n document: activeDocument,\n isDarkMode,\n theme: {\n styles: theme.themeStyles,\n themeStyleTag: theme.themeStyleTag,\n customThemes,\n },\n telemetry,\n }\n}\n"],"mappings":"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"}
{"version":3,"file":"app-state.js","names":[],"sources":["../../../../src/v2/features/app/app-state.ts"],"sourcesContent":["import type { ScalarListboxOption, WorkspaceGroup } from '@scalar/components'\nimport { isDefined } from '@scalar/helpers/array/is-defined'\nimport { sortByOrder } from '@scalar/helpers/array/sort-by-order'\nimport type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport type { LoaderPlugin } from '@scalar/json-magic/bundle'\nimport { migrateLocalStorageToIndexDb } from '@scalar/oas-utils/migrations'\nimport { createSidebarState, generateReverseIndex } from '@scalar/sidebar'\nimport type { Theme } from '@scalar/themes'\nimport { type WorkspaceStore, createWorkspaceStore } from '@scalar/workspace-store/client'\n\nimport type { ApiClientAppOptions } from '@/v2/features/app/helpers/create-api-client-app'\nimport {\n type OperationExampleMeta,\n type WorkspaceEventBus,\n createWorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport { generateUniqueValue } from '@scalar/workspace-store/helpers/generate-unique-value'\nimport { getParentEntry } from '@scalar/workspace-store/navigation'\nimport { createWorkspaceStorePersistence, getWorkspaceId } from '@scalar/workspace-store/persistence'\nimport { persistencePlugin } from '@scalar/workspace-store/plugins/client'\nimport { getActiveEnvironment } from '@scalar/workspace-store/request-example'\nimport type { Workspace, WorkspaceDocument } from '@scalar/workspace-store/schemas'\nimport { extensions } from '@scalar/workspace-store/schemas/extensions'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { Tab } from '@scalar/workspace-store/schemas/extensions/workspace/x-scalar-tabs'\nimport type { TraversedEntry } from '@scalar/workspace-store/schemas/navigation'\nimport {\n type ComputedRef,\n type MaybeRefOrGetter,\n type Ref,\n type ShallowRef,\n computed,\n readonly,\n ref,\n shallowRef,\n watch,\n} from 'vue'\nimport type { RouteLocationNormalizedGeneric, RouteLocationRaw, Router } from 'vue-router'\n\nimport { getRouteParam } from '@/v2/features/app/helpers/get-route-param'\nimport { groupWorkspacesByTeam } from '@/v2/features/app/helpers/group-workspaces'\nimport { useTheme } from '@/v2/features/app/hooks/use-theme'\nimport { getTabDetails } from '@/v2/helpers/get-tab-details'\nimport { slugify } from '@/v2/helpers/slugify'\nimport { workspaceStorage } from '@/v2/helpers/storage'\n\nimport { initializeAppEventHandlers } from './app-events'\nimport { canLoadWorkspace, filterWorkspacesByTeam } from './helpers/filter-workspaces'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\nexport type GetEntryByLocation = (location: {\n document: string\n path?: string\n method?: HttpMethod\n example?: string\n}) =>\n | (TraversedEntry & {\n parent?: TraversedEntry | undefined\n })\n | undefined\n\ntype WorkspaceOption = ScalarListboxOption & { teamUid: string; namespace: string; slug: string }\n\n/** Defines the overall application state structure and its main feature modules */\nexport type AppState = {\n /** The workspace store */\n store: ShallowRef<WorkspaceStore | null>\n /** The sidebar management */\n sidebar: {\n /** The sidebar state */\n state: ReturnType<typeof createSidebarState<TraversedEntry>>\n /** The width of the sidebar */\n width: ComputedRef<number>\n /** Whether the sidebar is open */\n isOpen: Ref<boolean>\n /** Handles the selection of an item in the sidebar */\n handleSelectItem: (id: string) => void\n /** Handles the width update of the sidebar */\n handleSidebarWidthUpdate: (width: number) => void\n /** Gets the entry by location */\n getEntryByLocation: GetEntryByLocation\n }\n /** The tabs management */\n tabs: {\n /** The tabs state */\n state: Ref<Tab[]>\n /** The active tab index */\n activeTabIndex: Ref<number>\n /** Copies the URL of the tab at the given index to the clipboard */\n copyTabUrl: (index: number) => Promise<void>\n }\n /** The workspace management */\n workspace: {\n /** Creates a new workspace and navigates to it */\n create: (payload: {\n teamUid?: string\n namespace?: string\n slug?: string\n name: string\n }) => Promise<{ name: string; namespace: string; slug: string; teamUid: string } | undefined>\n /** All workspace list */\n workspaceList: Ref<WorkspaceOption[]>\n /** Filtered workspace list, based on the current teamUid */\n filteredWorkspaceList: ComputedRef<WorkspaceOption[]>\n /**\n * Groups workspaces into team and local categories for display in the workspace picker.\n * Team workspaces are shown first (when not on local team), followed by local workspaces.\n */\n workspaceGroups: ComputedRef<WorkspaceGroup[]>\n /** The currently active workspace */\n activeWorkspace: ShallowRef<{ id: string; label: string } | null>\n /** Navigates to the specified workspace */\n navigateToWorkspace: (namespace?: string, slug?: string) => Promise<void>\n /** Whether the workspace page is open */\n isOpen: ComputedRef<boolean>\n }\n /** The workspace event bus for handling workspace-level events */\n eventBus: WorkspaceEventBus\n /** The router instance */\n router: Router\n /** The current route derived from the router */\n currentRoute: Ref<RouteLocationNormalizedGeneric | null>\n /** Whether the workspace is currently syncing */\n loading: Ref<boolean>\n /** Runtime behaviour overrides */\n options?: ApiClientAppOptions\n /** The currently active entities */\n activeEntities: {\n /** The namespace of the current entity, e.g. \"default\" or a custom namespace */\n namespace: Ref<string | undefined>\n /** The slug identifying the current workspace */\n workspaceSlug: Ref<string | undefined>\n /** The slug of the currently selected document in the workspace */\n documentSlug: Ref<string | undefined>\n /** The API path currently selected (e.g. \"/users/{id}\") */\n path: Ref<string | undefined>\n /** The HTTP method for the currently selected API path (e.g. GET, POST) */\n method: Ref<HttpMethod | undefined>\n /** The name of the currently selected example (for examples within an endpoint) */\n exampleName: Ref<string | undefined>\n /** The unique identifier for the selected team context (read-only; use setTeamUid to change) */\n teamUid: Readonly<Ref<string>>\n /** Sets the current team context by team UID */\n setTeamUid: (value: string) => void\n }\n /** The currently active environment */\n environment: ComputedRef<XScalarEnvironment>\n /** The currently active document */\n document: ComputedRef<WorkspaceDocument | null>\n /** Whether the current color mode is dark */\n isDarkMode: ComputedRef<boolean>\n /** The currently active theme */\n theme: {\n /** The computed CSS styles for the current theme, as a string */\n styles: ComputedRef<{ themeStyles: string; themeSlug: string }>\n /** The computed value for the <style> tag containing the current theme styles */\n themeStyleTag: ComputedRef<string>\n /** The custom themes to use */\n customThemes: MaybeRefOrGetter<Theme[]>\n }\n telemetry: Ref<boolean>\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n/** Default debounce delay in milliseconds for workspace store persistence. */\nconst DEFAULT_DEBOUNCE_DELAY = 1000\n/** Default sidebar width in pixels. */\nconst DEFAULT_SIDEBAR_WIDTH = 288\n\n// ---------------------------------------------------------------------------\n// App State\n// ---------------------------------------------------------------------------\nexport const createAppState = async ({\n router,\n fileLoader,\n fallbackThemeSlug = () => 'default',\n customThemes = () => [],\n telemetryDefault,\n options,\n}: {\n router: Router\n fileLoader?: LoaderPlugin\n customThemes?: MaybeRefOrGetter<Theme[]>\n fallbackThemeSlug?: MaybeRefOrGetter<string>\n telemetryDefault?: boolean\n /** Runtime behaviour overrides */\n options?: ApiClientAppOptions\n}): Promise<AppState> => {\n /** Workspace event bus for handling workspace-level events. */\n const eventBus = createWorkspaceEventBus({\n debug: import.meta.env.DEV,\n })\n\n const { workspace: persistence } = await createWorkspaceStorePersistence()\n\n /**\n * Run migration from localStorage to IndexedDB if needed\n * This happens once per user and transforms old data structure to new workspace format\n */\n await migrateLocalStorageToIndexDb()\n\n // ---------------------------------------------------------------------------\n // Active entities\n // ---------------------------------------------------------------------------\n const teamUid = ref<string>('local')\n const namespace = ref<string | undefined>(undefined)\n const workspaceSlug = ref<string | undefined>(undefined)\n const documentSlug = ref<string | undefined>(undefined)\n const method = ref<HttpMethod | undefined>(undefined)\n const path = ref<string | undefined>(undefined)\n const exampleName = ref<string | undefined>(undefined)\n\n // ---------------------------------------------------------------------------\n // Loading states\n const isSyncingWorkspace = ref(false)\n\n // ---------------------------------------------------------------------------\n // Router state\n router.afterEach((to) => handleRouteChange(to))\n const currentRoute = computed(() => router.currentRoute.value ?? null)\n\n // ---------------------------------------------------------------------------\n // Workspace persistence state management\n const activeWorkspace = shallowRef<{ id: string; label: string } | null>(null)\n const workspaces = ref<WorkspaceOption[]>([])\n const filteredWorkspaces = computed(() => filterWorkspacesByTeam(workspaces.value, teamUid.value))\n const workspaceGroups = computed(() => groupWorkspacesByTeam(filteredWorkspaces.value, teamUid.value))\n const store = shallowRef<WorkspaceStore | null>(null)\n\n // Load persisted telemetry preference, falling back to the provided default\n const persistedTelemetry = workspaceStorage.getTelemetry()\n const telemetry = ref(persistedTelemetry !== null ? persistedTelemetry : Boolean(telemetryDefault))\n watch(telemetry, (value) => workspaceStorage.setTelemetry(value))\n\n const activeDocument = computed(() => {\n return store.value?.workspace.documents[documentSlug.value ?? ''] || null\n })\n\n /**\n * Merged environment variables from workspace and document levels.\n * Variables from both sources are combined, with document variables\n * taking precedence in case of naming conflicts.\n */\n const environment = computed<XScalarEnvironment>(\n () => getActiveEnvironment(store.value, activeDocument.value).environment,\n )\n\n /** Update the workspace list when the component is mounted */\n workspaces.value = await persistence.getAll().then((w) =>\n w.map(({ teamUid, namespace, slug, name }) => ({\n id: getWorkspaceId(namespace, slug),\n teamUid,\n namespace,\n slug,\n label: name,\n })),\n )\n\n /**\n * Renames the currently active workspace.\n * Updates the workspace name in persistence and updates activeWorkspace if successful.\n * Returns early if namespace or workspaceSlug is not set, or if update fails.\n */\n const renameWorkspace = async (name: string) => {\n const namespaceValue = namespace.value\n const slugValue = workspaceSlug.value\n if (!namespaceValue || !slugValue) {\n return\n }\n const workspaceId = getWorkspaceId(namespaceValue, slugValue)\n const updateResult = await persistence.updateName({ namespace: namespaceValue, slug: slugValue }, name)\n\n // If the update fails, return early\n if (updateResult === undefined) {\n return\n }\n\n // Update the workspace list\n workspaces.value = workspaces.value.map((workspace) => {\n // If the workspace is the currently active workspace, update the label\n if (workspace.id === workspaceId) {\n return { ...workspace, label: name }\n }\n return workspace\n })\n activeWorkspace.value = { id: workspaceId, label: name }\n }\n\n /**\n * Creates a client-side workspace store with persistence enabled for the given workspace id.\n */\n const createClientStore = async ({\n namespace,\n slug,\n }: {\n namespace: string\n slug: string\n }): Promise<WorkspaceStore> => {\n return createWorkspaceStore({\n plugins: [\n await persistencePlugin({\n workspaceId: getWorkspaceId(namespace, slug),\n debounceDelay: DEFAULT_DEBOUNCE_DELAY,\n }),\n ],\n fileLoader,\n fetch: options?.customFetch,\n })\n }\n\n /**\n * Attempts to load and activate a workspace by id.\n * Returns true when the workspace was found and activated.\n */\n const loadWorkspace = async (\n namespace: string,\n slug: string,\n ): Promise<{ success: true; workspace: Workspace } | { success: false }> => {\n const workspace = await persistence.getItem({ namespace, slug })\n\n if (!workspace) {\n return {\n success: false,\n }\n }\n\n const client = await createClientStore({ namespace, slug })\n client.loadWorkspace(workspace.workspace)\n activeWorkspace.value = { id: getWorkspaceId(workspace.namespace, workspace.slug), label: workspace.name }\n store.value = client\n\n return {\n success: true,\n workspace: client.workspace,\n }\n }\n\n /**\n * Creates and persists the default workspace with a blank draft document.\n * Used when no workspaces exist yet.\n */\n const createAndPersistWorkspace = async ({\n name,\n teamUid,\n namespace,\n slug,\n }: {\n name: string\n teamUid?: string\n namespace?: string\n slug: string\n }) => {\n const draftStore = createWorkspaceStore()\n await draftStore.addDocument({\n name: 'drafts',\n document: {\n openapi: '3.1.0',\n info: {\n title: 'Drafts',\n version: '1.0.0',\n },\n paths: {\n '/': {\n get: {},\n },\n },\n 'x-scalar-original-document-hash': 'drafts',\n 'x-scalar-icon': 'interface-edit-tool-pencil',\n },\n })\n\n // Persist the workspace\n const workspace = await persistence.setItem(\n { namespace, slug },\n {\n name: name,\n teamUid,\n workspace: draftStore.exportWorkspace(),\n },\n )\n\n // Update the workspace list\n workspaces.value.push({\n id: getWorkspaceId(workspace.namespace, workspace.slug),\n teamUid: workspace.teamUid,\n namespace: workspace.namespace,\n slug: workspace.slug,\n label: workspace.name,\n })\n return workspace\n }\n\n /**\n * Navigates to the overview page of the specified workspace.\n *\n * @param namespace - The workspace namespace.\n * @param slug - The unique workspace slug (identifier).\n */\n const navigateToWorkspace = async (namespace?: string, slug?: string): Promise<void> => {\n if (!namespace || !slug) {\n await router.push('/')\n return\n }\n\n // We should always have this drafts document available in a new workspace\n await router.push({\n name: 'example',\n params: {\n namespace,\n workspaceSlug: slug,\n documentSlug: 'drafts',\n pathEncoded: encodeURIComponent('/'),\n method: 'get',\n exampleName: 'default',\n },\n })\n }\n\n /**\n * Creates a new workspace with the provided name.\n * - Generates a unique slug for the workspace (uses the provided slug if it is unique, otherwise generates a unique slug).\n * - Adds a default blank document (\"drafts\") to the workspace.\n * - Persists the workspace and navigates to it.\n *\n * Example usage:\n * await createWorkspace({ name: 'My Awesome API' })\n * // -> Navigates to /workspace/my-awesome-api (if available)\n */\n const createWorkspace = async ({\n teamUid,\n namespace,\n slug,\n name,\n }: {\n teamUid?: string\n namespace?: string\n slug?: string\n name: string\n }) => {\n // Clear up the current store, in order to show the loading state\n store.value = null\n\n // Generate a unique slug/id for the workspace, based on the name.\n const newWorkspaceSlug = await generateUniqueValue({\n defaultValue: slug ?? name, // Use the provided id if it exists, otherwise use the name\n validation: async (value) => !(await persistence.has({ namespace: namespace ?? 'local', slug: value })),\n maxRetries: 100,\n transformation: slugify,\n })\n\n // Failed to generate a unique workspace id, so we can't create the workspace.\n if (!newWorkspaceSlug) {\n return undefined\n }\n\n const newWorkspaceDetails = {\n teamUid,\n namespace,\n slug: newWorkspaceSlug,\n name,\n }\n\n // Create a new client store with the workspace ID and add a default document.\n const createdWorkspace = await createAndPersistWorkspace(newWorkspaceDetails)\n\n // Navigate to the newly created workspace.\n await navigateToWorkspace(createdWorkspace.namespace, createdWorkspace.slug)\n return createdWorkspace\n }\n\n /**\n * Handles changing the active workspace when the workspace slug changes in the route.\n * This function:\n * - Clears the current workspace store and sets loading state.\n * - Attempts to load the workspace by slug.\n * - If found, navigates to the active tab path (if available).\n * - If not found, creates the default workspace and navigates to it.\n */\n const changeWorkspace = async (namespace: string, slug: string) => {\n // Clear the current store and set loading to true before loading new workspace.\n store.value = null\n isSyncingWorkspace.value = true\n\n // Try to load the workspace\n const result = await loadWorkspace(namespace, slug)\n\n if (result.success) {\n // Navigate to the correct tab if the workspace has a tab already\n const index = result.workspace['x-scalar-active-tab'] ?? 0\n const tabs = result.workspace['x-scalar-tabs']\n const tab = tabs?.[index]\n\n if (tab) {\n // Preserve query parameters when navigating to the active tab\n await router.replace({\n path: tab.path,\n query: currentRoute.value?.query ?? {},\n })\n }\n\n // Heal the active tab index if it is out of bounds\n if (tabs && index >= tabs.length) {\n eventBus.emit('tabs:update:tabs', {\n 'x-scalar-active-tab': 0,\n })\n }\n\n // Initialize the tabs if they does not exist\n if (!tabs) {\n eventBus.emit('tabs:update:tabs', {\n 'x-scalar-tabs': [createTabFromRoute(currentRoute.value)],\n 'x-scalar-active-tab': 0,\n })\n }\n\n isSyncingWorkspace.value = false\n return\n }\n\n // Navigate to the default workspace, or fall back to the first available workspace\n const targetWorkspace =\n filteredWorkspaces.value.find((workspace) => workspace.teamUid === 'local' && workspace.slug === 'default') ??\n filteredWorkspaces.value[0]\n\n if (targetWorkspace) {\n return navigateToWorkspace(targetWorkspace.namespace, targetWorkspace.slug)\n }\n\n // If loading failed (workspace does not exist), create the default workspace and navigate to it.\n const createResult = await createWorkspace({\n name: 'Default Workspace',\n slug: 'default',\n })\n\n isSyncingWorkspace.value = false\n\n if (!createResult) {\n return console.error('Failed to create the default workspace, something went wrong, can not load the workspace')\n }\n\n // Must reset the sidebar state when the workspace changes\n sidebarState.reset()\n }\n\n /**\n * Sets the current team context. If the active workspace is not accessible\n * with the new team, navigates to the default workspace for that team.\n */\n const setTeamUid = (value: string) => {\n // Update the new teamUid\n teamUid.value = value\n\n // Find the current workspace\n const workspace = filteredWorkspaces.value.find(\n (w) => w.namespace === namespace.value && w.slug === workspaceSlug.value,\n )\n\n // Check if new teamUid is accessible to the current workspace\n if (workspace && canLoadWorkspace(workspace.teamUid, value)) {\n return\n }\n\n return navigateToWorkspace('local', 'default')\n }\n\n // ---------------------------------------------------------------------------\n // Sidebar state management\n\n const entries = computed(() => {\n const activeStore = store.value\n if (!activeStore) {\n return []\n }\n\n const order = activeStore.workspace['x-scalar-order'] ?? Object.keys(activeStore.workspace.documents)\n\n return sortByOrder(Object.keys(activeStore.workspace.documents), order, (item) => item)\n .map((doc) => activeStore.workspace.documents[doc]?.['x-scalar-navigation'])\n .filter(isDefined) as TraversedEntry[]\n })\n\n const sidebarState = createSidebarState(entries)\n\n /**\n * Generates a unique string ID for an API location, based on the document, path, method, and example.\n * Filters out undefined values and serializes the composite array into a stable string.\n *\n * @param params - An object containing document, path, method, and optional example name.\n * @returns A stringified array representing the unique location identifier.\n *\n * Example:\n * generateId({ document: 'mydoc', path: '/users', method: 'get', example: 'default' })\n * // => '[\"mydoc\",\"/users\",\"get\",\"default\"]'\n */\n const generateId = ({\n document,\n path,\n method,\n example,\n }: {\n document: string\n path?: string\n method?: HttpMethod\n example?: string\n }) => {\n return JSON.stringify([document, path, method, example].filter(isDefined))\n }\n\n /**\n * Computed index for fast lookup of sidebar nodes by their unique API location.\n *\n * - Only indexes nodes of type 'document', 'operation', or 'example'.\n * - The lookup key is a serialized array of: [documentName, operationPath, operationMethod, exampleName?].\n * - Supports precise resolution of sidebar entries given an API \"location\".\n */\n const locationIndex = computed(() =>\n generateReverseIndex({\n items: entries.value,\n nestedKey: 'children',\n filter: (node) => node.type === 'document' || node.type === 'operation' || node.type === 'example',\n getId: (node) => {\n const document = getParentEntry('document', node)\n const operation = getParentEntry('operation', node)\n return generateId({\n document: document?.name ?? '',\n path: operation?.path,\n method: operation?.method,\n example: node.type === 'example' ? node.name : undefined,\n })\n },\n }),\n )\n\n /**\n * Looks up a sidebar entry by its unique API location.\n * - First tries to find an entry matching all provided properties (including example).\n * - If not found, falls back to matching only the operation (ignores example field).\n * This allows resolving either examples, operations, or documents as appropriate.\n *\n * @param location - Object specifying the document name, path, method, and optional example name.\n * @returns The matching sidebar entry, or undefined if none found.\n *\n * Example:\n * const entry = getEntryByLocation({\n * document: 'pets',\n * path: '/pets',\n * method: 'get',\n * example: 'default',\n * })\n */\n const getEntryByLocation: GetEntryByLocation = (location) => {\n // Try to find an entry with the most-specific location (including example)\n const entryWithExample = locationIndex.value.get(generateId(location))\n\n if (entryWithExample) {\n return entryWithExample\n }\n\n // Fallback to the operation (ignoring example) if an example wasn't found or specified\n return locationIndex.value.get(\n generateId({\n document: location.document,\n path: location.path,\n method: location.method,\n }),\n )\n }\n\n /**\n * Handles item selection from the sidebar and routes navigation accordingly.\n *\n * Example:\n * handleSelectItem('id-of-entry')\n */\n const handleSelectItem = (id: string) => {\n const entry = sidebarState.getEntryById(id)\n\n if (!entry) {\n console.warn(`Could not find sidebar entry with id ${id} to select`)\n return\n }\n\n /** Close sidebar and navigate. Used for every branch that performs navigation. */\n const navigate = (route: RouteLocationRaw) => {\n isSidebarOpen.value = false\n return router.push(route)\n }\n\n // Navigate to the document overview page\n if (entry.type === 'document') {\n // If we are already in the document, just toggle expansion\n if (sidebarState.selectedItem.value === id) {\n sidebarState.setExpanded(id, !sidebarState.isExpanded(id))\n return\n }\n\n // Otherwise, select it\n sidebarState.setSelected(id)\n sidebarState.setExpanded(id, true)\n return navigate({\n name: 'document.overview',\n params: { documentSlug: entry.name },\n })\n }\n\n // Navigate to the example page\n if (entry.type === 'operation') {\n // If we are already in an operation child we just want to toggle the explanstion\n if (sidebarState.isSelected(id) && sidebarState.selectedItem.value !== id) {\n sidebarState.setExpanded(id, !sidebarState.isExpanded(id))\n return\n }\n\n // Otherwise, select the first example\n const firstExample = entry.children?.find((child) => child.type === 'example')\n\n if (firstExample) {\n sidebarState.setSelected(firstExample.id)\n sidebarState.setExpanded(firstExample.id, true)\n } else {\n sidebarState.setSelected(id)\n }\n\n return navigate({\n name: 'example',\n params: {\n documentSlug: getParentEntry('document', entry)?.name,\n pathEncoded: encodeURIComponent(entry.path),\n method: entry.method,\n exampleName: firstExample?.name ?? 'default',\n },\n })\n }\n\n // Navigate to the example page\n if (entry.type === 'example') {\n sidebarState.setSelected(id)\n const operation = getParentEntry('operation', entry)\n return navigate({\n name: 'example',\n params: {\n documentSlug: getParentEntry('document', entry)?.name,\n pathEncoded: encodeURIComponent(operation?.path ?? ''),\n method: operation?.method,\n exampleName: entry.name,\n },\n })\n }\n\n if (entry.type === 'text') {\n return navigate({\n name: 'document.overview',\n params: {\n documentSlug: getParentEntry('document', entry)?.name,\n },\n })\n }\n\n sidebarState.setExpanded(id, !sidebarState.isExpanded(id))\n return\n }\n\n /**\n * Navigates to the currently active tab's path using the router.\n * Returns early if the workspace store or active tab is unavailable.\n */\n const navigateToCurrentTab = async (): Promise<void> => {\n if (!store.value) {\n return\n }\n\n const activeTabIndex = store.value.workspace['x-scalar-active-tab'] ?? 0\n const activeTab = store.value.workspace['x-scalar-tabs']?.[activeTabIndex]\n if (!activeTab) {\n return\n }\n\n await router.replace(activeTab.path)\n }\n\n /**\n * Rebuilds the sidebar for the given document.\n * This is used to refresh the sidebar state after structural changes (e.g. after adding or removing items).\n *\n * @param documentName - The name (id) of the document for which to rebuild the sidebar\n */\n const rebuildSidebar = (documentName: string | undefined) => {\n if (documentName) {\n store.value?.buildSidebar(documentName)\n }\n }\n\n /**\n * Ensures the sidebar is refreshed after a new example is created.\n *\n * If the sidebar entry for the new example does not exist or is of a different type,\n * this will rebuild the sidebar for the current document. This helps keep the sidebar state\n * consistent (e.g., after adding a new example via the UI).\n */\n const refreshSidebarAfterExampleCreation = (payload: OperationExampleMeta & { documentName?: string }) => {\n const documentName = payload.documentName ?? activeDocument.value?.['x-scalar-navigation']?.name\n if (!documentName) {\n return\n }\n\n const entry = getEntryByLocation({\n document: documentName,\n path: payload.path,\n method: payload.method,\n example: payload.exampleKey,\n })\n\n if (!entry || entry.type !== 'example') {\n // Sidebar entry for this example doesn't exist, so rebuild sidebar for consistency.\n rebuildSidebar(documentName)\n if (currentRoute.value) {\n syncSidebar(currentRoute.value)\n }\n }\n return\n }\n\n /** Width of the sidebar, with fallback to default. */\n const sidebarWidth = computed(() => store.value?.workspace?.['x-scalar-sidebar-width'] ?? DEFAULT_SIDEBAR_WIDTH)\n\n /** Handler for sidebar width changes. */\n const handleSidebarWidthUpdate = (width: number) => store.value?.update('x-scalar-sidebar-width', width)\n\n /** Controls the visibility of the sidebar. */\n const isSidebarOpen = ref(false)\n // ---------------------------------------------------------------------------\n // Tab Management\n\n /** Constants for workspace store keys */\n const TABS_KEY = 'x-scalar-tabs' as const\n const ACTIVE_TAB_KEY = 'x-scalar-active-tab' as const\n\n /**\n * Creates a tab object based on the current route and workspace state.\n * Used as a fallback when no tabs exist or when creating new tabs.\n */\n const createTabFromRoute = (to: RouteLocationNormalizedGeneric | null): Tab => {\n const method = getRouteParam('method', to)\n const path = getRouteParam('pathEncoded', to)\n const document = getRouteParam('documentSlug', to)\n const workspace = getRouteParam('workspaceSlug', to)\n return {\n ...getTabDetails({\n workspace,\n document,\n path,\n method,\n getEntryByLocation,\n }),\n path: currentRoute.value?.path ?? '',\n }\n }\n\n const tabs = computed(() => {\n return store.value?.workspace[TABS_KEY] ?? [createTabFromRoute(currentRoute.value)]\n })\n\n const activeTabIndex = computed(() => {\n return store.value?.workspace[ACTIVE_TAB_KEY] ?? 0\n })\n\n /**\n * Copies the URL of the tab at the given index to the clipboard.\n * Constructs the full URL using the current origin and the tab path.\n *\n * Note: Will silently fail if clipboard API is unavailable or the tab does not exist.\n */\n const copyTabUrl = async (index: number): Promise<void> => {\n const tab = tabs.value[index]\n\n if (!tab) {\n console.warn(`Cannot copy URL: tab at index ${index} does not exist`)\n return\n }\n\n const url = `${window.location.origin}${tab.path}`\n\n try {\n await navigator.clipboard.writeText(url)\n } catch (error) {\n console.error('Failed to copy URL to clipboard:', error)\n }\n }\n\n // ---------------------------------------------------------------------------\n // Path syncing\n\n /** When the route changes we need to update the active entities in the store */\n const handleRouteChange = (to: RouteLocationNormalizedGeneric) => {\n const slug = getRouteParam('workspaceSlug', to)\n const document = getRouteParam('documentSlug', to)\n const namespaceValue = getRouteParam('namespace', to)\n\n // Must have an active workspace to syncs\n if (!namespaceValue || !slug) {\n return\n }\n\n // Try to see if the user can load this workspace based on the teamUid and namespace\n const workspace = workspaces.value.find(\n (workspace) => workspace.slug === slug && workspace.namespace === namespaceValue,\n )\n\n // If the workspace is not found or the teamUid does not match, try to redirect to the default workspace\n if (workspace && !canLoadWorkspace(workspace.teamUid, teamUid.value)) {\n // try to redirect to the default workspace\n return navigateToWorkspace('local', 'default')\n }\n\n namespace.value = namespaceValue\n workspaceSlug.value = slug\n documentSlug.value = document\n method.value = getRouteParam('method', to)\n path.value = getRouteParam('pathEncoded', to)\n exampleName.value = getRouteParam('exampleName', to)\n\n // Save the current path to the persistence storage\n if (to.path !== '') {\n workspaceStorage.setCurrentPath(to.path)\n }\n\n if (getWorkspaceId(namespace.value, slug) !== activeWorkspace.value?.id) {\n return changeWorkspace(namespace.value, slug)\n }\n\n // Update the active document if the document slug has changes\n if (document && document !== store.value?.workspace[extensions.workspace.activeDocument]) {\n store?.value?.update('x-scalar-active-document', document)\n }\n\n syncTabs(to)\n syncSidebar(to)\n return\n }\n\n /** Aligns the tabs with any potential slug changes */\n const syncTabs = (to: RouteLocationNormalizedGeneric) => {\n const tabs = store.value?.workspace['x-scalar-tabs'] ?? []\n const index = store.value?.workspace['x-scalar-active-tab'] ?? 0\n\n const tab = tabs[index]\n\n // If there is no tab or the tab path is the same we leave the tab state alone\n if (!tab || tab.path === to.path) {\n // Already on the correct path, do nothing\n return\n }\n\n // Otherwise we replace the tab content with the new route\n tabs[index] = createTabFromRoute(to)\n }\n\n /** Aligns the sidebar state with any potential slug changes */\n const syncSidebar = (to: RouteLocationNormalizedGeneric) => {\n const document = getRouteParam('documentSlug', to)\n\n if (!document) {\n // Reset selection if no document is selected\n sidebarState.setSelected(null)\n return\n }\n\n const entry = getEntryByLocation({\n document,\n path: getRouteParam('pathEncoded', to),\n method: getRouteParam('method', to),\n example: getRouteParam('exampleName', to),\n })\n\n if (entry) {\n sidebarState.setSelected(entry.id)\n sidebarState.setExpanded(entry.id, true)\n }\n }\n\n // ---------------------------------------------------------------------------\n // Events handling\n\n initializeAppEventHandlers({\n eventBus,\n router,\n store,\n navigateToCurrentTab,\n rebuildSidebar,\n onAfterExampleCreation: refreshSidebarAfterExampleCreation,\n onSelectSidebarItem: handleSelectItem,\n onCopyTabUrl: (index) => copyTabUrl(index),\n onToggleSidebar: () => (isSidebarOpen.value = !isSidebarOpen.value),\n closeSidebar: () => (isSidebarOpen.value = false),\n renameWorkspace,\n })\n\n const theme = useTheme({\n fallbackThemeSlug,\n customThemes,\n store: store,\n })\n\n const isDarkMode = computed(() => {\n const colorMode = store.value?.workspace['x-scalar-color-mode'] ?? 'system'\n if (colorMode === 'system') {\n return window.matchMedia?.('(prefers-color-scheme: dark)')?.matches ?? false\n }\n return colorMode === 'dark'\n })\n\n return {\n /** Active workspace store */\n store,\n sidebar: {\n state: sidebarState,\n width: sidebarWidth,\n isOpen: isSidebarOpen,\n handleSelectItem,\n handleSidebarWidthUpdate,\n getEntryByLocation,\n },\n tabs: {\n state: tabs,\n activeTabIndex,\n copyTabUrl,\n },\n workspace: {\n create: createWorkspace,\n workspaceList: workspaces,\n filteredWorkspaceList: filteredWorkspaces,\n workspaceGroups,\n activeWorkspace,\n navigateToWorkspace,\n isOpen: computed(() => Boolean(workspaceSlug.value && !documentSlug.value)),\n },\n eventBus,\n router,\n currentRoute,\n loading: isSyncingWorkspace,\n activeEntities: {\n namespace,\n workspaceSlug,\n documentSlug,\n path,\n method,\n exampleName,\n teamUid: readonly(teamUid),\n setTeamUid,\n },\n environment,\n document: activeDocument,\n isDarkMode,\n theme: {\n styles: theme.themeStyles,\n themeStyleTag: theme.themeStyleTag,\n customThemes,\n },\n telemetry,\n options,\n }\n}\n"],"mappings":"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"}

@@ -1,1 +0,1 @@

{"version":3,"file":"App.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/features/app/App.vue"],"names":[],"mappings":"AAsRA,OAAO,EAGL,KAAK,UAAU,EAChB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAW7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+DAA+D,CAAA;AAKxG,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAA;AAC1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAErD,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAA;AAK3C;;;;GAIG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;YAER,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC;cAC5B,YAAY,EAAE;iBACX,MAAM,QAAQ;4BACH,MAAM,mBAAmB;IACjD,+FAA+F;4BACvE,0BAA0B;;;;YAL1C,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC;cAC5B,YAAY,EAAE;iBACX,MAAM,QAAQ;4BACH,MAAM,mBAAmB;IACjD,+FAA+F;4BACvE,0BAA0B;;IAYlD;;;OAGG;4BACqB,MAAM,OAAO;IACrC;;;OAGG;yBACkB,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,UAAU,CAAA;KAAE,KAAK,OAAO;EAsX9D,CAAC;AACL,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
{"version":3,"file":"App.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/features/app/App.vue"],"names":[],"mappings":"AAuRA,OAAO,EAGL,KAAK,UAAU,EAChB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAW7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+DAA+D,CAAA;AAKxG,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAA;AAC1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAErD,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAA;AAK3C;;;;GAIG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;YAER,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC;cAC5B,YAAY,EAAE;iBACX,MAAM,QAAQ;4BACH,MAAM,mBAAmB;IACjD,+FAA+F;4BACvE,0BAA0B;;;;YAL1C,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC;cAC5B,YAAY,EAAE;iBACX,MAAM,QAAQ;4BACH,MAAM,mBAAmB;IACjD,+FAA+F;4BACvE,0BAA0B;;IAYlD;;;OAGG;4BACqB,MAAM,OAAO;IACrC;;;OAGG;yBACkB,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,UAAU,CAAA;KAAE,KAAK,OAAO;EAuX9D,CAAC;AACL,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}

@@ -1,1 +0,1 @@

{"version":3,"file":"App.vue.js","names":[],"sources":["../../../../src/v2/features/app/App.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Main entry point for the API client for electron and web.\n *\n * This component handles all events and store business logic for the application.\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n ScalarTeleportRoot,\n useModal,\n type ModalState,\n} from '@scalar/components'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport { ScalarToasts } from '@scalar/use-toasts'\nimport { extensions } from '@scalar/workspace-store/schemas/extensions'\nimport { computed, onBeforeUnmount, toValue, watch } from 'vue'\nimport { RouterView } from 'vue-router'\n\nimport { SidebarToggle } from '@/v2/components/sidebar'\nimport CreateWorkspaceModal from '@/v2/features/app/components/CreateWorkspaceModal.vue'\nimport SplashScreen from '@/v2/features/app/components/SplashScreen.vue'\nimport type { RouteProps } from '@/v2/features/app/helpers/routes'\nimport { useDocumentWatcher } from '@/v2/features/app/hooks/use-document-watcher'\nimport type { CommandPaletteState } from '@/v2/features/command-palette/hooks/use-command-palette-state'\nimport TheCommandPalette from '@/v2/features/command-palette/TheCommandPalette.vue'\nimport { useMonacoEditorConfiguration } from '@/v2/features/editor'\nimport { useColorMode } from '@/v2/hooks/use-color-mode'\nimport { useGlobalHotKeys } from '@/v2/hooks/use-global-hot-keys'\nimport type { ImportDocumentFromRegistry } from '@/v2/types/configuration'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nimport { type AppState } from './app-state'\nimport AppSidebar from './components/AppSidebar.vue'\nimport DesktopTabs from './components/DesktopTabs.vue'\n\nconst {\n layout,\n plugins = [],\n getAppState,\n getCommandPaletteState,\n fetchRegistryDocument,\n} = defineProps<{\n layout: Exclude<ClientLayout, 'modal'>\n plugins?: ClientPlugin[]\n getAppState: () => AppState\n getCommandPaletteState: () => CommandPaletteState\n /** Fetches the full document from registry by meta. Passed through to route props for sync. */\n fetchRegistryDocument?: ImportDocumentFromRegistry\n}>()\n\ndefineSlots<{\n /**\n * Slot for customizing the actions section of the sidebar menu.\n * This slot is used to render custom actions or components within the actions section.\n */\n 'sidebar-menu-actions': () => unknown\n /**\n * Slot for customizing the create workspace modal.\n * This slot is used to render custom actions or components within the create workspace modal.\n */\n 'create-workspace'?: (payload: { state: ModalState }) => unknown\n}>()\n\ndefineExpose({\n openCreateWorkspace: () => createWorkspaceModalState.show(),\n})\n\nconst app = getAppState()\nconst paletteState = getCommandPaletteState()\n\n/** Expose workspace store to window for debugging purposes. */\nif (typeof window !== 'undefined') {\n window.dataDumpWorkspace = () => app.store.value\n window.dumpAppState = () => app\n}\n\n/** Call lifecycle hooks on plugins and subscribe to event bus events */\nconst pluginUnsubscribes: (() => void)[] = []\n\nfor (const plugin of plugins) {\n plugin.lifecycle?.onInit?.({ config: { telemetry: app.telemetry.value } })\n\n if (plugin.on) {\n for (const [event, handler] of Object.entries(plugin.on)) {\n pluginUnsubscribes.push(app.eventBus.on(event as any, handler as any))\n }\n }\n}\n\n/** Notify plugins when telemetry config changes */\nwatch(app.telemetry, () => {\n for (const plugin of plugins) {\n plugin.lifecycle?.onConfigChange?.({\n config: { telemetry: app.telemetry.value },\n })\n }\n})\n\nonBeforeUnmount(() => {\n for (const unsub of pluginUnsubscribes) {\n unsub()\n }\n for (const plugin of plugins) {\n plugin.lifecycle?.onDestroy?.()\n }\n})\n\n/** Register global hotkeys for the app, passing the workspace event bus and layout state */\nuseGlobalHotKeys(app.eventBus, layout)\n\nconst DEFAULT_DOCUMENT_WATCH_TIMEOUT = 5000\n\n/** Watch the active document for changes and rebase it with its remote source */\nuseDocumentWatcher({\n documentName: () =>\n app.store.value?.workspace[extensions.workspace.activeDocument],\n store: app.store,\n initialTimeout: DEFAULT_DOCUMENT_WATCH_TIMEOUT,\n})\n\n/** Color mode */\nuseColorMode({ workspaceStore: app.store })\n\nconst currentTheme = computed(() => app.theme.styles.value.themeStyles)\nconst isDarkMode = computed(() => app.isDarkMode.value)\n\n/** Setup monaco editor configuration */\nuseMonacoEditorConfiguration({\n theme: currentTheme,\n darkMode: isDarkMode,\n})\n\nconst navigateToWorkspaceOverview = (namespace?: string, slug?: string) => {\n app.eventBus.emit('ui:navigate', {\n page: 'workspace',\n path: 'environment',\n namespace,\n workspaceSlug: slug,\n })\n}\n\n/** Sets the active workspace by ID: finds the workspace in the list and updates app state & navigation. */\nconst setActiveWorkspace = (id?: string) => {\n if (!id) {\n return\n }\n const workspace = app.workspace.workspaceList.value?.find(\n (workspace) => workspace.id === id,\n )\n if (!workspace) {\n return\n }\n\n navigateToWorkspaceOverview(workspace.namespace, workspace.slug)\n}\n\nconst createWorkspaceModalState = useModal()\n\n/** Props to pass to the RouterView component. */\nconst routerViewProps = computed<RouteProps>(() => {\n return {\n documentSlug: app.activeEntities.documentSlug.value ?? '',\n document: app.store.value?.workspace.activeDocument ?? null,\n environment: app.environment.value,\n eventBus: app.eventBus,\n exampleName: app.activeEntities.exampleName.value,\n fetchRegistryDocument,\n layout,\n method: app.activeEntities.method.value,\n path: app.activeEntities.path.value,\n workspaceStore: app.store.value!,\n activeWorkspace: app.workspace.activeWorkspace.value!,\n plugins,\n isDarkMode: app.isDarkMode.value,\n currentTheme: app.theme.styles.value.themeStyles,\n customThemes: toValue(app.theme.customThemes),\n telemetry: app.telemetry.value,\n onUpdateTelemetry: (value: boolean) => {\n app.telemetry.value = value\n },\n }\n})\n</script>\n\n<template>\n <ScalarTeleportRoot>\n <!-- Theme style tag -->\n <div v-html=\"app.theme.themeStyleTag.value\" />\n\n <!-- Toasts -->\n <ScalarToasts />\n\n <!-- Main content -->\n <main\n v-if=\"\n app.store.value !== null &&\n app.workspace.activeWorkspace.value !== null &&\n !app.loading.value\n \">\n <div class=\"relative flex h-dvh w-dvw flex-1 flex-col\">\n <SidebarToggle\n v-model=\"app.sidebar.isOpen.value\"\n class=\"absolute top-4 left-3 z-[60] md:hidden\" />\n <div class=\"flex min-h-0 flex-1 flex-row\">\n <!-- App sidebar -->\n <AppSidebar\n v-model:isSidebarOpen=\"app.sidebar.isOpen.value\"\n :activeWorkspace=\"app.workspace.activeWorkspace.value\"\n :eventBus=\"app.eventBus\"\n :isWorkspaceOpen=\"app.workspace.isOpen.value\"\n :layout\n :sidebarState=\"app.sidebar.state\"\n :sidebarWidth=\"app.sidebar.width.value\"\n :store=\"app.store.value!\"\n :workspaces=\"app.workspace.workspaceGroups.value\"\n @click:workspace=\"navigateToWorkspaceOverview\"\n @create:workspace=\"createWorkspaceModalState.show()\"\n @select:workspace=\"setActiveWorkspace\"\n @selectItem=\"app.sidebar.handleSelectItem\"\n @update:sidebarWidth=\"app.sidebar.handleSidebarWidthUpdate\">\n <template #sidebarMenuActions>\n <slot name=\"sidebar-menu-actions\" />\n </template>\n </AppSidebar>\n\n <div class=\"flex flex-1 flex-col\">\n <!-- App Tabs -->\n <DesktopTabs\n v-if=\"layout === 'desktop'\"\n :activeTabIndex=\"app.tabs.activeTabIndex.value\"\n :eventBus=\"app.eventBus\"\n :tabs=\"app.tabs.state.value\" />\n\n <!-- Router view min-h-0 is required for scrolling, do not remove it -->\n <div class=\"bg-b-1 relative min-h-0 flex-1\">\n <RouterView v-bind=\"routerViewProps\" />\n </div>\n </div>\n </div>\n </div>\n\n <slot\n name=\"create-workspace\"\n :state=\"createWorkspaceModalState\">\n <!-- Create workspace modal -->\n <CreateWorkspaceModal\n :state=\"createWorkspaceModalState\"\n @create:workspace=\"(payload) => app.workspace.create(payload)\" />\n </slot>\n\n <!-- Popup command palette to add resources from anywhere -->\n <TheCommandPalette\n :eventBus=\"app.eventBus\"\n :paletteState=\"paletteState\"\n :workspaceStore=\"app.store.value!\" />\n </main>\n <!-- Splash screen -->\n <main v-else>\n <SplashScreen />\n </main>\n </ScalarTeleportRoot>\n</template>\n\n<style>\n#scalar-client {\n position: relative;\n background-color: var(--scalar-background-2);\n}\n.dark-mode #scalar-client {\n background-color: color-mix(in srgb, var(--scalar-background-1) 65%, black);\n}\n</style>\n"],"mappings":""}
{"version":3,"file":"App.vue.js","names":[],"sources":["../../../../src/v2/features/app/App.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Main entry point for the API client for electron and web.\n *\n * This component handles all events and store business logic for the application.\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n ScalarTeleportRoot,\n useModal,\n type ModalState,\n} from '@scalar/components'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport { ScalarToasts } from '@scalar/use-toasts'\nimport { extensions } from '@scalar/workspace-store/schemas/extensions'\nimport { computed, onBeforeUnmount, toValue, watch } from 'vue'\nimport { RouterView } from 'vue-router'\n\nimport { SidebarToggle } from '@/v2/components/sidebar'\nimport CreateWorkspaceModal from '@/v2/features/app/components/CreateWorkspaceModal.vue'\nimport SplashScreen from '@/v2/features/app/components/SplashScreen.vue'\nimport type { RouteProps } from '@/v2/features/app/helpers/routes'\nimport { useDocumentWatcher } from '@/v2/features/app/hooks/use-document-watcher'\nimport type { CommandPaletteState } from '@/v2/features/command-palette/hooks/use-command-palette-state'\nimport TheCommandPalette from '@/v2/features/command-palette/TheCommandPalette.vue'\nimport { useMonacoEditorConfiguration } from '@/v2/features/editor'\nimport { useColorMode } from '@/v2/hooks/use-color-mode'\nimport { useGlobalHotKeys } from '@/v2/hooks/use-global-hot-keys'\nimport type { ImportDocumentFromRegistry } from '@/v2/types/configuration'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nimport { type AppState } from './app-state'\nimport AppSidebar from './components/AppSidebar.vue'\nimport DesktopTabs from './components/DesktopTabs.vue'\n\nconst {\n layout,\n plugins = [],\n getAppState,\n getCommandPaletteState,\n fetchRegistryDocument,\n} = defineProps<{\n layout: Exclude<ClientLayout, 'modal'>\n plugins?: ClientPlugin[]\n getAppState: () => AppState\n getCommandPaletteState: () => CommandPaletteState\n /** Fetches the full document from registry by meta. Passed through to route props for sync. */\n fetchRegistryDocument?: ImportDocumentFromRegistry\n}>()\n\ndefineSlots<{\n /**\n * Slot for customizing the actions section of the sidebar menu.\n * This slot is used to render custom actions or components within the actions section.\n */\n 'sidebar-menu-actions': () => unknown\n /**\n * Slot for customizing the create workspace modal.\n * This slot is used to render custom actions or components within the create workspace modal.\n */\n 'create-workspace'?: (payload: { state: ModalState }) => unknown\n}>()\n\ndefineExpose({\n openCreateWorkspace: () => createWorkspaceModalState.show(),\n})\n\nconst app = getAppState()\nconst paletteState = getCommandPaletteState()\n\n/** Expose workspace store to window for debugging purposes. */\nif (typeof window !== 'undefined') {\n window.dataDumpWorkspace = () => app.store.value\n window.dumpAppState = () => app\n}\n\n/** Call lifecycle hooks on plugins and subscribe to event bus events */\nconst pluginUnsubscribes: (() => void)[] = []\n\nfor (const plugin of plugins) {\n plugin.lifecycle?.onInit?.({ config: { telemetry: app.telemetry.value } })\n\n if (plugin.on) {\n for (const [event, handler] of Object.entries(plugin.on)) {\n pluginUnsubscribes.push(app.eventBus.on(event as any, handler as any))\n }\n }\n}\n\n/** Notify plugins when telemetry config changes */\nwatch(app.telemetry, () => {\n for (const plugin of plugins) {\n plugin.lifecycle?.onConfigChange?.({\n config: { telemetry: app.telemetry.value },\n })\n }\n})\n\nonBeforeUnmount(() => {\n for (const unsub of pluginUnsubscribes) {\n unsub()\n }\n for (const plugin of plugins) {\n plugin.lifecycle?.onDestroy?.()\n }\n})\n\n/** Register global hotkeys for the app, passing the workspace event bus and layout state */\nuseGlobalHotKeys(app.eventBus, layout)\n\nconst DEFAULT_DOCUMENT_WATCH_TIMEOUT = 5000\n\n/** Watch the active document for changes and rebase it with its remote source */\nuseDocumentWatcher({\n documentName: () =>\n app.store.value?.workspace[extensions.workspace.activeDocument],\n store: app.store,\n initialTimeout: DEFAULT_DOCUMENT_WATCH_TIMEOUT,\n})\n\n/** Color mode */\nuseColorMode({ workspaceStore: app.store })\n\nconst currentTheme = computed(() => app.theme.styles.value.themeStyles)\nconst isDarkMode = computed(() => app.isDarkMode.value)\n\n/** Setup monaco editor configuration */\nuseMonacoEditorConfiguration({\n theme: currentTheme,\n darkMode: isDarkMode,\n})\n\nconst navigateToWorkspaceOverview = (namespace?: string, slug?: string) => {\n app.eventBus.emit('ui:navigate', {\n page: 'workspace',\n path: 'environment',\n namespace,\n workspaceSlug: slug,\n })\n}\n\n/** Sets the active workspace by ID: finds the workspace in the list and updates app state & navigation. */\nconst setActiveWorkspace = (id?: string) => {\n if (!id) {\n return\n }\n const workspace = app.workspace.workspaceList.value?.find(\n (workspace) => workspace.id === id,\n )\n if (!workspace) {\n return\n }\n\n navigateToWorkspaceOverview(workspace.namespace, workspace.slug)\n}\n\nconst createWorkspaceModalState = useModal()\n\n/** Props to pass to the RouterView component. */\nconst routerViewProps = computed<RouteProps>(() => {\n return {\n documentSlug: app.activeEntities.documentSlug.value ?? '',\n document: app.store.value?.workspace.activeDocument ?? null,\n environment: app.environment.value,\n eventBus: app.eventBus,\n exampleName: app.activeEntities.exampleName.value,\n fetchRegistryDocument,\n layout,\n method: app.activeEntities.method.value,\n path: app.activeEntities.path.value,\n workspaceStore: app.store.value!,\n activeWorkspace: app.workspace.activeWorkspace.value!,\n plugins,\n isDarkMode: app.isDarkMode.value,\n currentTheme: app.theme.styles.value.themeStyles,\n customThemes: toValue(app.theme.customThemes),\n telemetry: app.telemetry.value,\n onUpdateTelemetry: (value: boolean) => {\n app.telemetry.value = value\n },\n options: app.options,\n }\n})\n</script>\n\n<template>\n <ScalarTeleportRoot>\n <!-- Theme style tag -->\n <div v-html=\"app.theme.themeStyleTag.value\" />\n\n <!-- Toasts -->\n <ScalarToasts />\n\n <!-- Main content -->\n <main\n v-if=\"\n app.store.value !== null &&\n app.workspace.activeWorkspace.value !== null &&\n !app.loading.value\n \">\n <div class=\"relative flex h-dvh w-dvw flex-1 flex-col\">\n <SidebarToggle\n v-model=\"app.sidebar.isOpen.value\"\n class=\"absolute top-4 left-3 z-[60] md:hidden\" />\n <div class=\"flex min-h-0 flex-1 flex-row\">\n <!-- App sidebar -->\n <AppSidebar\n v-model:isSidebarOpen=\"app.sidebar.isOpen.value\"\n :activeWorkspace=\"app.workspace.activeWorkspace.value\"\n :eventBus=\"app.eventBus\"\n :isWorkspaceOpen=\"app.workspace.isOpen.value\"\n :layout\n :sidebarState=\"app.sidebar.state\"\n :sidebarWidth=\"app.sidebar.width.value\"\n :store=\"app.store.value!\"\n :workspaces=\"app.workspace.workspaceGroups.value\"\n @click:workspace=\"navigateToWorkspaceOverview\"\n @create:workspace=\"createWorkspaceModalState.show()\"\n @select:workspace=\"setActiveWorkspace\"\n @selectItem=\"app.sidebar.handleSelectItem\"\n @update:sidebarWidth=\"app.sidebar.handleSidebarWidthUpdate\">\n <template #sidebarMenuActions>\n <slot name=\"sidebar-menu-actions\" />\n </template>\n </AppSidebar>\n\n <div class=\"flex flex-1 flex-col\">\n <!-- App Tabs -->\n <DesktopTabs\n v-if=\"layout === 'desktop'\"\n :activeTabIndex=\"app.tabs.activeTabIndex.value\"\n :eventBus=\"app.eventBus\"\n :tabs=\"app.tabs.state.value\" />\n\n <!-- Router view min-h-0 is required for scrolling, do not remove it -->\n <div class=\"bg-b-1 relative min-h-0 flex-1\">\n <RouterView v-bind=\"routerViewProps\" />\n </div>\n </div>\n </div>\n </div>\n\n <slot\n name=\"create-workspace\"\n :state=\"createWorkspaceModalState\">\n <!-- Create workspace modal -->\n <CreateWorkspaceModal\n :state=\"createWorkspaceModalState\"\n @create:workspace=\"(payload) => app.workspace.create(payload)\" />\n </slot>\n\n <!-- Popup command palette to add resources from anywhere -->\n <TheCommandPalette\n :eventBus=\"app.eventBus\"\n :paletteState=\"paletteState\"\n :workspaceStore=\"app.store.value!\" />\n </main>\n <!-- Splash screen -->\n <main v-else>\n <SplashScreen />\n </main>\n </ScalarTeleportRoot>\n</template>\n\n<style>\n#scalar-client {\n position: relative;\n background-color: var(--scalar-background-2);\n}\n.dark-mode #scalar-client {\n background-color: color-mix(in srgb, var(--scalar-background-1) 65%, black);\n}\n</style>\n"],"mappings":""}

@@ -108,3 +108,4 @@ import TheCommandPalette_default from "../command-palette/TheCommandPalette.vue.js";

app.telemetry.value = value;
}
},
options: app.options
};

@@ -111,0 +112,0 @@ });

@@ -1,1 +0,1 @@

{"version":3,"file":"App.vue.script.js","names":[],"sources":["../../../../src/v2/features/app/App.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Main entry point for the API client for electron and web.\n *\n * This component handles all events and store business logic for the application.\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n ScalarTeleportRoot,\n useModal,\n type ModalState,\n} from '@scalar/components'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport { ScalarToasts } from '@scalar/use-toasts'\nimport { extensions } from '@scalar/workspace-store/schemas/extensions'\nimport { computed, onBeforeUnmount, toValue, watch } from 'vue'\nimport { RouterView } from 'vue-router'\n\nimport { SidebarToggle } from '@/v2/components/sidebar'\nimport CreateWorkspaceModal from '@/v2/features/app/components/CreateWorkspaceModal.vue'\nimport SplashScreen from '@/v2/features/app/components/SplashScreen.vue'\nimport type { RouteProps } from '@/v2/features/app/helpers/routes'\nimport { useDocumentWatcher } from '@/v2/features/app/hooks/use-document-watcher'\nimport type { CommandPaletteState } from '@/v2/features/command-palette/hooks/use-command-palette-state'\nimport TheCommandPalette from '@/v2/features/command-palette/TheCommandPalette.vue'\nimport { useMonacoEditorConfiguration } from '@/v2/features/editor'\nimport { useColorMode } from '@/v2/hooks/use-color-mode'\nimport { useGlobalHotKeys } from '@/v2/hooks/use-global-hot-keys'\nimport type { ImportDocumentFromRegistry } from '@/v2/types/configuration'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nimport { type AppState } from './app-state'\nimport AppSidebar from './components/AppSidebar.vue'\nimport DesktopTabs from './components/DesktopTabs.vue'\n\nconst {\n layout,\n plugins = [],\n getAppState,\n getCommandPaletteState,\n fetchRegistryDocument,\n} = defineProps<{\n layout: Exclude<ClientLayout, 'modal'>\n plugins?: ClientPlugin[]\n getAppState: () => AppState\n getCommandPaletteState: () => CommandPaletteState\n /** Fetches the full document from registry by meta. Passed through to route props for sync. */\n fetchRegistryDocument?: ImportDocumentFromRegistry\n}>()\n\ndefineSlots<{\n /**\n * Slot for customizing the actions section of the sidebar menu.\n * This slot is used to render custom actions or components within the actions section.\n */\n 'sidebar-menu-actions': () => unknown\n /**\n * Slot for customizing the create workspace modal.\n * This slot is used to render custom actions or components within the create workspace modal.\n */\n 'create-workspace'?: (payload: { state: ModalState }) => unknown\n}>()\n\ndefineExpose({\n openCreateWorkspace: () => createWorkspaceModalState.show(),\n})\n\nconst app = getAppState()\nconst paletteState = getCommandPaletteState()\n\n/** Expose workspace store to window for debugging purposes. */\nif (typeof window !== 'undefined') {\n window.dataDumpWorkspace = () => app.store.value\n window.dumpAppState = () => app\n}\n\n/** Call lifecycle hooks on plugins and subscribe to event bus events */\nconst pluginUnsubscribes: (() => void)[] = []\n\nfor (const plugin of plugins) {\n plugin.lifecycle?.onInit?.({ config: { telemetry: app.telemetry.value } })\n\n if (plugin.on) {\n for (const [event, handler] of Object.entries(plugin.on)) {\n pluginUnsubscribes.push(app.eventBus.on(event as any, handler as any))\n }\n }\n}\n\n/** Notify plugins when telemetry config changes */\nwatch(app.telemetry, () => {\n for (const plugin of plugins) {\n plugin.lifecycle?.onConfigChange?.({\n config: { telemetry: app.telemetry.value },\n })\n }\n})\n\nonBeforeUnmount(() => {\n for (const unsub of pluginUnsubscribes) {\n unsub()\n }\n for (const plugin of plugins) {\n plugin.lifecycle?.onDestroy?.()\n }\n})\n\n/** Register global hotkeys for the app, passing the workspace event bus and layout state */\nuseGlobalHotKeys(app.eventBus, layout)\n\nconst DEFAULT_DOCUMENT_WATCH_TIMEOUT = 5000\n\n/** Watch the active document for changes and rebase it with its remote source */\nuseDocumentWatcher({\n documentName: () =>\n app.store.value?.workspace[extensions.workspace.activeDocument],\n store: app.store,\n initialTimeout: DEFAULT_DOCUMENT_WATCH_TIMEOUT,\n})\n\n/** Color mode */\nuseColorMode({ workspaceStore: app.store })\n\nconst currentTheme = computed(() => app.theme.styles.value.themeStyles)\nconst isDarkMode = computed(() => app.isDarkMode.value)\n\n/** Setup monaco editor configuration */\nuseMonacoEditorConfiguration({\n theme: currentTheme,\n darkMode: isDarkMode,\n})\n\nconst navigateToWorkspaceOverview = (namespace?: string, slug?: string) => {\n app.eventBus.emit('ui:navigate', {\n page: 'workspace',\n path: 'environment',\n namespace,\n workspaceSlug: slug,\n })\n}\n\n/** Sets the active workspace by ID: finds the workspace in the list and updates app state & navigation. */\nconst setActiveWorkspace = (id?: string) => {\n if (!id) {\n return\n }\n const workspace = app.workspace.workspaceList.value?.find(\n (workspace) => workspace.id === id,\n )\n if (!workspace) {\n return\n }\n\n navigateToWorkspaceOverview(workspace.namespace, workspace.slug)\n}\n\nconst createWorkspaceModalState = useModal()\n\n/** Props to pass to the RouterView component. */\nconst routerViewProps = computed<RouteProps>(() => {\n return {\n documentSlug: app.activeEntities.documentSlug.value ?? '',\n document: app.store.value?.workspace.activeDocument ?? null,\n environment: app.environment.value,\n eventBus: app.eventBus,\n exampleName: app.activeEntities.exampleName.value,\n fetchRegistryDocument,\n layout,\n method: app.activeEntities.method.value,\n path: app.activeEntities.path.value,\n workspaceStore: app.store.value!,\n activeWorkspace: app.workspace.activeWorkspace.value!,\n plugins,\n isDarkMode: app.isDarkMode.value,\n currentTheme: app.theme.styles.value.themeStyles,\n customThemes: toValue(app.theme.customThemes),\n telemetry: app.telemetry.value,\n onUpdateTelemetry: (value: boolean) => {\n app.telemetry.value = value\n },\n }\n})\n</script>\n\n<template>\n <ScalarTeleportRoot>\n <!-- Theme style tag -->\n <div v-html=\"app.theme.themeStyleTag.value\" />\n\n <!-- Toasts -->\n <ScalarToasts />\n\n <!-- Main content -->\n <main\n v-if=\"\n app.store.value !== null &&\n app.workspace.activeWorkspace.value !== null &&\n !app.loading.value\n \">\n <div class=\"relative flex h-dvh w-dvw flex-1 flex-col\">\n <SidebarToggle\n v-model=\"app.sidebar.isOpen.value\"\n class=\"absolute top-4 left-3 z-[60] md:hidden\" />\n <div class=\"flex min-h-0 flex-1 flex-row\">\n <!-- App sidebar -->\n <AppSidebar\n v-model:isSidebarOpen=\"app.sidebar.isOpen.value\"\n :activeWorkspace=\"app.workspace.activeWorkspace.value\"\n :eventBus=\"app.eventBus\"\n :isWorkspaceOpen=\"app.workspace.isOpen.value\"\n :layout\n :sidebarState=\"app.sidebar.state\"\n :sidebarWidth=\"app.sidebar.width.value\"\n :store=\"app.store.value!\"\n :workspaces=\"app.workspace.workspaceGroups.value\"\n @click:workspace=\"navigateToWorkspaceOverview\"\n @create:workspace=\"createWorkspaceModalState.show()\"\n @select:workspace=\"setActiveWorkspace\"\n @selectItem=\"app.sidebar.handleSelectItem\"\n @update:sidebarWidth=\"app.sidebar.handleSidebarWidthUpdate\">\n <template #sidebarMenuActions>\n <slot name=\"sidebar-menu-actions\" />\n </template>\n </AppSidebar>\n\n <div class=\"flex flex-1 flex-col\">\n <!-- App Tabs -->\n <DesktopTabs\n v-if=\"layout === 'desktop'\"\n :activeTabIndex=\"app.tabs.activeTabIndex.value\"\n :eventBus=\"app.eventBus\"\n :tabs=\"app.tabs.state.value\" />\n\n <!-- Router view min-h-0 is required for scrolling, do not remove it -->\n <div class=\"bg-b-1 relative min-h-0 flex-1\">\n <RouterView v-bind=\"routerViewProps\" />\n </div>\n </div>\n </div>\n </div>\n\n <slot\n name=\"create-workspace\"\n :state=\"createWorkspaceModalState\">\n <!-- Create workspace modal -->\n <CreateWorkspaceModal\n :state=\"createWorkspaceModalState\"\n @create:workspace=\"(payload) => app.workspace.create(payload)\" />\n </slot>\n\n <!-- Popup command palette to add resources from anywhere -->\n <TheCommandPalette\n :eventBus=\"app.eventBus\"\n :paletteState=\"paletteState\"\n :workspaceStore=\"app.store.value!\" />\n </main>\n <!-- Splash screen -->\n <main v-else>\n <SplashScreen />\n </main>\n </ScalarTeleportRoot>\n</template>\n\n<style>\n#scalar-client {\n position: relative;\n background-color: var(--scalar-background-2);\n}\n.dark-mode #scalar-client {\n background-color: color-mix(in srgb, var(--scalar-background-1) 65%, black);\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkEA,WAAa,EACX,2BAA2B,0BAA0B,MAAM,EAC5D,CAAA;EAED,MAAM,MAAM,QAAA,aAAY;EACxB,MAAM,eAAe,QAAA,wBAAuB;;AAG5C,MAAI,OAAO,WAAW,aAAa;AACjC,UAAO,0BAA0B,IAAI,MAAM;AAC3C,UAAO,qBAAqB;;;EAI9B,MAAM,qBAAqC,EAAC;AAE5C,OAAK,MAAM,UAAU,QAAA,SAAS;AAC5B,UAAO,WAAW,SAAS,EAAE,QAAQ,EAAE,WAAW,IAAI,UAAU,OAAO,EAAE,CAAA;AAEzE,OAAI,OAAO,GACT,MAAK,MAAM,CAAC,OAAO,YAAY,OAAO,QAAQ,OAAO,GAAG,CACtD,oBAAmB,KAAK,IAAI,SAAS,GAAG,OAAc,QAAe,CAAA;;;AAM3E,QAAM,IAAI,iBAAiB;AACzB,QAAK,MAAM,UAAU,QAAA,QACnB,QAAO,WAAW,iBAAiB,EACjC,QAAQ,EAAE,WAAW,IAAI,UAAU,OAAO,EAC3C,CAAA;IAEJ;AAED,wBAAsB;AACpB,QAAK,MAAM,SAAS,mBAClB,QAAM;AAER,QAAK,MAAM,UAAU,QAAA,QACnB,QAAO,WAAW,aAAY;IAEjC;;AAGD,mBAAiB,IAAI,UAAU,QAAA,OAAM;;AAKrC,qBAAmB;GACjB,oBACE,IAAI,MAAM,OAAO,UAAU,WAAW,UAAU;GAClD,OAAO,IAAI;GACX,gBAPqC;GAQtC,CAAA;;AAGD,eAAa,EAAE,gBAAgB,IAAI,OAAO,CAAA;;AAM1C,+BAA6B;GAC3B,OALmB,eAAe,IAAI,MAAM,OAAO,MAAM,YAAW;GAMpE,UALiB,eAAe,IAAI,WAAW,MAAK;GAMrD,CAAA;EAED,MAAM,+BAA+B,WAAoB,SAAkB;AACzE,OAAI,SAAS,KAAK,eAAe;IAC/B,MAAM;IACN,MAAM;IACN;IACA,eAAe;IAChB,CAAA;;;EAIH,MAAM,sBAAsB,OAAgB;AAC1C,OAAI,CAAC,GACH;GAEF,MAAM,YAAY,IAAI,UAAU,cAAc,OAAO,MAClD,cAAc,UAAU,OAAO,GAClC;AACA,OAAI,CAAC,UACH;AAGF,+BAA4B,UAAU,WAAW,UAAU,KAAI;;EAGjE,MAAM,4BAA4B,UAAS;;EAG3C,MAAM,kBAAkB,eAA2B;AACjD,UAAO;IACL,cAAc,IAAI,eAAe,aAAa,SAAS;IACvD,UAAU,IAAI,MAAM,OAAO,UAAU,kBAAkB;IACvD,aAAa,IAAI,YAAY;IAC7B,UAAU,IAAI;IACd,aAAa,IAAI,eAAe,YAAY;IAC5C,uBAAoB,QAAA;IACpB,QAAK,QAAA;IACL,QAAQ,IAAI,eAAe,OAAO;IAClC,MAAM,IAAI,eAAe,KAAK;IAC9B,gBAAgB,IAAI,MAAM;IAC1B,iBAAiB,IAAI,UAAU,gBAAgB;IAC/C,SAAM,QAAA;IACN,YAAY,IAAI,WAAW;IAC3B,cAAc,IAAI,MAAM,OAAO,MAAM;IACrC,cAAc,QAAQ,IAAI,MAAM,aAAa;IAC7C,WAAW,IAAI,UAAU;IACzB,oBAAoB,UAAmB;AACrC,SAAI,UAAU,QAAQ;;IAE1B;IACD;;uBAIC,YA2EqB,MAAA,mBAAA,EAAA,MAAA;2BAzE2B;KAA9C,mBAA8C,OAAA,EAAzC,WAAQ,MAAA,IAAG,CAAC,MAAM,cAAc,OAAA,EAAA,MAAA,GAAA,WAAA;KAGrC,YAAgB,MAAA,aAAA,CAAA;KAIC,MAAA,IAAG,CAAC,MAAM,UAAK,QAAqB,MAAA,IAAG,CAAC,UAAU,gBAAgB,UAAK,QAAA,CAAsB,MAAA,IAAG,CAAC,QAAQ,SAAA,WAAA,EAD1H,mBA8DO,QAAA,YAAA;MAxDL,mBAwCM,OAxCN,YAwCM,CAvCJ,YAEmD,MAAA,sBAAA,EAAA;mBADxC,MAAA,IAAG,CAAC,QAAQ,OAAO;0EAAnB,IAAG,CAAC,QAAQ,OAAO,QAAK;OACjC,OAAM;mCACR,mBAmCM,OAnCN,YAmCM,CAjCJ,YAkBa,oBAAA;OAjBH,eAAe,MAAA,IAAG,CAAC,QAAQ,OAAO;6EAAnB,IAAG,CAAC,QAAQ,OAAO,QAAK;OAC9C,iBAAiB,MAAA,IAAG,CAAC,UAAU,gBAAgB;OAC/C,UAAU,MAAA,IAAG,CAAC;OACd,iBAAiB,MAAA,IAAG,CAAC,UAAU,OAAO;OACtC,QAAA,QAAA;OACA,cAAc,MAAA,IAAG,CAAC,QAAQ;OAC1B,cAAc,MAAA,IAAG,CAAC,QAAQ,MAAM;OAChC,OAAO,MAAA,IAAG,CAAC,MAAM;OACjB,YAAY,MAAA,IAAG,CAAC,UAAU,gBAAgB;OAC1C,qBAAiB;OACjB,sBAAgB,OAAA,OAAA,OAAA,MAAA,WAAE,MAAA,0BAAyB,CAAC,MAAI;OAChD,sBAAkB;OAClB,cAAY,MAAA,IAAG,CAAC,QAAQ;OACxB,yBAAqB,MAAA,IAAG,CAAC,QAAQ;;OACvB,oBAAkB,cACS,CAApC,WAAoC,KAAA,QAAA,uBAAA,CAAA,CAAA;;;;;;;;;;;;;;UAIxC,mBAYM,OAZN,YAYM,CATI,QAAA,WAAM,aAAA,WAAA,EADd,YAIiC,qBAAA;;OAF9B,gBAAgB,MAAA,IAAG,CAAC,KAAK,eAAe;OACxC,UAAU,MAAA,IAAG,CAAC;OACd,MAAM,MAAA,IAAG,CAAC,KAAK,MAAM;;;;;0CAGxB,mBAEM,OAFN,YAEM,CADJ,YAAuC,MAAA,WAAA,EAAA,eAAA,mBAAnB,gBAAA,MAAe,CAAA,EAAA,MAAA,GAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;MAM3C,WAOO,KAAA,QAAA,oBAAA,EALJ,OAAO,MAAA,0BAAyB,EAAA,QAK5B,CAHL,YAEmE,8BAAA;OADhE,OAAO,MAAA,0BAAyB;OAChC,sBAAgB,OAAA,OAAA,OAAA,MAAG,YAAY,MAAA,IAAG,CAAC,UAAU,OAAO,QAAO;;MAIhE,YAGuC,2BAAA;OAFpC,UAAU,MAAA,IAAG,CAAC;OACd,cAAc,MAAA,aAAY;OAC1B,gBAAgB,MAAA,IAAG,CAAC,MAAM;;;;;;yBAG/B,mBAEO,QAAA,YAAA,CADL,YAAgB,qBAAA,CAAA,CAAA"}
{"version":3,"file":"App.vue.script.js","names":[],"sources":["../../../../src/v2/features/app/App.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Main entry point for the API client for electron and web.\n *\n * This component handles all events and store business logic for the application.\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n ScalarTeleportRoot,\n useModal,\n type ModalState,\n} from '@scalar/components'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport { ScalarToasts } from '@scalar/use-toasts'\nimport { extensions } from '@scalar/workspace-store/schemas/extensions'\nimport { computed, onBeforeUnmount, toValue, watch } from 'vue'\nimport { RouterView } from 'vue-router'\n\nimport { SidebarToggle } from '@/v2/components/sidebar'\nimport CreateWorkspaceModal from '@/v2/features/app/components/CreateWorkspaceModal.vue'\nimport SplashScreen from '@/v2/features/app/components/SplashScreen.vue'\nimport type { RouteProps } from '@/v2/features/app/helpers/routes'\nimport { useDocumentWatcher } from '@/v2/features/app/hooks/use-document-watcher'\nimport type { CommandPaletteState } from '@/v2/features/command-palette/hooks/use-command-palette-state'\nimport TheCommandPalette from '@/v2/features/command-palette/TheCommandPalette.vue'\nimport { useMonacoEditorConfiguration } from '@/v2/features/editor'\nimport { useColorMode } from '@/v2/hooks/use-color-mode'\nimport { useGlobalHotKeys } from '@/v2/hooks/use-global-hot-keys'\nimport type { ImportDocumentFromRegistry } from '@/v2/types/configuration'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nimport { type AppState } from './app-state'\nimport AppSidebar from './components/AppSidebar.vue'\nimport DesktopTabs from './components/DesktopTabs.vue'\n\nconst {\n layout,\n plugins = [],\n getAppState,\n getCommandPaletteState,\n fetchRegistryDocument,\n} = defineProps<{\n layout: Exclude<ClientLayout, 'modal'>\n plugins?: ClientPlugin[]\n getAppState: () => AppState\n getCommandPaletteState: () => CommandPaletteState\n /** Fetches the full document from registry by meta. Passed through to route props for sync. */\n fetchRegistryDocument?: ImportDocumentFromRegistry\n}>()\n\ndefineSlots<{\n /**\n * Slot for customizing the actions section of the sidebar menu.\n * This slot is used to render custom actions or components within the actions section.\n */\n 'sidebar-menu-actions': () => unknown\n /**\n * Slot for customizing the create workspace modal.\n * This slot is used to render custom actions or components within the create workspace modal.\n */\n 'create-workspace'?: (payload: { state: ModalState }) => unknown\n}>()\n\ndefineExpose({\n openCreateWorkspace: () => createWorkspaceModalState.show(),\n})\n\nconst app = getAppState()\nconst paletteState = getCommandPaletteState()\n\n/** Expose workspace store to window for debugging purposes. */\nif (typeof window !== 'undefined') {\n window.dataDumpWorkspace = () => app.store.value\n window.dumpAppState = () => app\n}\n\n/** Call lifecycle hooks on plugins and subscribe to event bus events */\nconst pluginUnsubscribes: (() => void)[] = []\n\nfor (const plugin of plugins) {\n plugin.lifecycle?.onInit?.({ config: { telemetry: app.telemetry.value } })\n\n if (plugin.on) {\n for (const [event, handler] of Object.entries(plugin.on)) {\n pluginUnsubscribes.push(app.eventBus.on(event as any, handler as any))\n }\n }\n}\n\n/** Notify plugins when telemetry config changes */\nwatch(app.telemetry, () => {\n for (const plugin of plugins) {\n plugin.lifecycle?.onConfigChange?.({\n config: { telemetry: app.telemetry.value },\n })\n }\n})\n\nonBeforeUnmount(() => {\n for (const unsub of pluginUnsubscribes) {\n unsub()\n }\n for (const plugin of plugins) {\n plugin.lifecycle?.onDestroy?.()\n }\n})\n\n/** Register global hotkeys for the app, passing the workspace event bus and layout state */\nuseGlobalHotKeys(app.eventBus, layout)\n\nconst DEFAULT_DOCUMENT_WATCH_TIMEOUT = 5000\n\n/** Watch the active document for changes and rebase it with its remote source */\nuseDocumentWatcher({\n documentName: () =>\n app.store.value?.workspace[extensions.workspace.activeDocument],\n store: app.store,\n initialTimeout: DEFAULT_DOCUMENT_WATCH_TIMEOUT,\n})\n\n/** Color mode */\nuseColorMode({ workspaceStore: app.store })\n\nconst currentTheme = computed(() => app.theme.styles.value.themeStyles)\nconst isDarkMode = computed(() => app.isDarkMode.value)\n\n/** Setup monaco editor configuration */\nuseMonacoEditorConfiguration({\n theme: currentTheme,\n darkMode: isDarkMode,\n})\n\nconst navigateToWorkspaceOverview = (namespace?: string, slug?: string) => {\n app.eventBus.emit('ui:navigate', {\n page: 'workspace',\n path: 'environment',\n namespace,\n workspaceSlug: slug,\n })\n}\n\n/** Sets the active workspace by ID: finds the workspace in the list and updates app state & navigation. */\nconst setActiveWorkspace = (id?: string) => {\n if (!id) {\n return\n }\n const workspace = app.workspace.workspaceList.value?.find(\n (workspace) => workspace.id === id,\n )\n if (!workspace) {\n return\n }\n\n navigateToWorkspaceOverview(workspace.namespace, workspace.slug)\n}\n\nconst createWorkspaceModalState = useModal()\n\n/** Props to pass to the RouterView component. */\nconst routerViewProps = computed<RouteProps>(() => {\n return {\n documentSlug: app.activeEntities.documentSlug.value ?? '',\n document: app.store.value?.workspace.activeDocument ?? null,\n environment: app.environment.value,\n eventBus: app.eventBus,\n exampleName: app.activeEntities.exampleName.value,\n fetchRegistryDocument,\n layout,\n method: app.activeEntities.method.value,\n path: app.activeEntities.path.value,\n workspaceStore: app.store.value!,\n activeWorkspace: app.workspace.activeWorkspace.value!,\n plugins,\n isDarkMode: app.isDarkMode.value,\n currentTheme: app.theme.styles.value.themeStyles,\n customThemes: toValue(app.theme.customThemes),\n telemetry: app.telemetry.value,\n onUpdateTelemetry: (value: boolean) => {\n app.telemetry.value = value\n },\n options: app.options,\n }\n})\n</script>\n\n<template>\n <ScalarTeleportRoot>\n <!-- Theme style tag -->\n <div v-html=\"app.theme.themeStyleTag.value\" />\n\n <!-- Toasts -->\n <ScalarToasts />\n\n <!-- Main content -->\n <main\n v-if=\"\n app.store.value !== null &&\n app.workspace.activeWorkspace.value !== null &&\n !app.loading.value\n \">\n <div class=\"relative flex h-dvh w-dvw flex-1 flex-col\">\n <SidebarToggle\n v-model=\"app.sidebar.isOpen.value\"\n class=\"absolute top-4 left-3 z-[60] md:hidden\" />\n <div class=\"flex min-h-0 flex-1 flex-row\">\n <!-- App sidebar -->\n <AppSidebar\n v-model:isSidebarOpen=\"app.sidebar.isOpen.value\"\n :activeWorkspace=\"app.workspace.activeWorkspace.value\"\n :eventBus=\"app.eventBus\"\n :isWorkspaceOpen=\"app.workspace.isOpen.value\"\n :layout\n :sidebarState=\"app.sidebar.state\"\n :sidebarWidth=\"app.sidebar.width.value\"\n :store=\"app.store.value!\"\n :workspaces=\"app.workspace.workspaceGroups.value\"\n @click:workspace=\"navigateToWorkspaceOverview\"\n @create:workspace=\"createWorkspaceModalState.show()\"\n @select:workspace=\"setActiveWorkspace\"\n @selectItem=\"app.sidebar.handleSelectItem\"\n @update:sidebarWidth=\"app.sidebar.handleSidebarWidthUpdate\">\n <template #sidebarMenuActions>\n <slot name=\"sidebar-menu-actions\" />\n </template>\n </AppSidebar>\n\n <div class=\"flex flex-1 flex-col\">\n <!-- App Tabs -->\n <DesktopTabs\n v-if=\"layout === 'desktop'\"\n :activeTabIndex=\"app.tabs.activeTabIndex.value\"\n :eventBus=\"app.eventBus\"\n :tabs=\"app.tabs.state.value\" />\n\n <!-- Router view min-h-0 is required for scrolling, do not remove it -->\n <div class=\"bg-b-1 relative min-h-0 flex-1\">\n <RouterView v-bind=\"routerViewProps\" />\n </div>\n </div>\n </div>\n </div>\n\n <slot\n name=\"create-workspace\"\n :state=\"createWorkspaceModalState\">\n <!-- Create workspace modal -->\n <CreateWorkspaceModal\n :state=\"createWorkspaceModalState\"\n @create:workspace=\"(payload) => app.workspace.create(payload)\" />\n </slot>\n\n <!-- Popup command palette to add resources from anywhere -->\n <TheCommandPalette\n :eventBus=\"app.eventBus\"\n :paletteState=\"paletteState\"\n :workspaceStore=\"app.store.value!\" />\n </main>\n <!-- Splash screen -->\n <main v-else>\n <SplashScreen />\n </main>\n </ScalarTeleportRoot>\n</template>\n\n<style>\n#scalar-client {\n position: relative;\n background-color: var(--scalar-background-2);\n}\n.dark-mode #scalar-client {\n background-color: color-mix(in srgb, var(--scalar-background-1) 65%, black);\n}\n</style>\n"],"mappings":"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"}

@@ -13,4 +13,4 @@ import type { Tab } from '@scalar/workspace-store/schemas/extensions/workspace';

declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
click: () => any;
close: () => any;
click: () => any;
copyUrl: () => any;

@@ -20,4 +20,4 @@ newTab: () => any;

}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
onClick?: (() => any) | undefined;
onClose?: (() => any) | undefined;
onClick?: (() => any) | undefined;
onCopyUrl?: (() => any) | undefined;

@@ -24,0 +24,0 @@ onNewTab?: (() => any) | undefined;

@@ -5,2 +5,3 @@ import type { ClientPlugin } from '@scalar/oas-utils/helpers';

import type { ClientLayout } from '../../../../v2/types/layout';
import type { ApiClientOptions } from '../../../../v2/types/options';
type CreateApiClientOptions = {

@@ -36,4 +37,11 @@ /**

telemetry?: boolean;
/** Runtime behaviour overrides */
options?: ApiClientAppOptions;
};
/**
* Runtime behaviour overrides shared between createApiClientApp and createAppState.
* Derived from the canonical ApiClientOptions to guarantee structural compatibility.
*/
export type ApiClientAppOptions = Pick<ApiClientOptions, 'customFetch' | 'oauth2RedirectUri'>;
/**
* Creates the appropriate router with the appropriate routes based on the layout

@@ -45,3 +53,3 @@ */

*/
export declare const createApiClientApp: (el: HTMLElement | null, { layout, plugins, customThemes, fallbackThemeSlug, fetchRegistryDocument, telemetry, }: CreateApiClientOptions) => Promise<{
export declare const createApiClientApp: (el: HTMLElement | null, { layout, plugins, customThemes, fallbackThemeSlug, fetchRegistryDocument, telemetry, options, }: CreateApiClientOptions) => Promise<{
app: import("vue").App<Element>;

@@ -48,0 +56,0 @@ state: import("../../../../v2/features/app/app-state.js").AppState;

@@ -1,1 +0,1 @@

{"version":3,"file":"create-api-client-app.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/app/helpers/create-api-client-app.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAO3C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAA;AAC1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAIrD,KAAK,sBAAsB,GAAG;IAC5B;;;;;OAKG;IACH,MAAM,EAAE,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,CAAA;IACtC;;OAEG;IACH,OAAO,CAAC,EAAE,YAAY,EAAE,CAAA;IACxB;;OAEG;IACH,YAAY,CAAC,EAAE,KAAK,EAAE,CAAA;IACtB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,MAAM,CAAA;IAChC;;;OAGG;IACH,qBAAqB,CAAC,EAAE,0BAA0B,CAAA;IAClD;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,QAAQ,sBAAsB,CAAC,QAAQ,CAAC,gCAQvE,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAC7B,IAAI,WAAW,GAAG,IAAI,EACtB,yFAOG,sBAAsB;;;cAsC1B,CAAA"}
{"version":3,"file":"create-api-client-app.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/app/helpers/create-api-client-app.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAO3C,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAA;AAC1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAI1D,KAAK,sBAAsB,GAAG;IAC5B;;;;;OAKG;IACH,MAAM,EAAE,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,CAAA;IACtC;;OAEG;IACH,OAAO,CAAC,EAAE,YAAY,EAAE,CAAA;IACxB;;OAEG;IACH,YAAY,CAAC,EAAE,KAAK,EAAE,CAAA;IACtB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,MAAM,CAAA;IAChC;;;OAGG;IACH,qBAAqB,CAAC,EAAE,0BAA0B,CAAA;IAClD;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,kCAAkC;IAClC,OAAO,CAAC,EAAE,mBAAmB,CAAA;CAC9B,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,gBAAgB,EAAE,aAAa,GAAG,mBAAmB,CAAC,CAAA;AAE7F;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,QAAQ,sBAAsB,CAAC,QAAQ,CAAC,gCAQvE,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAC7B,IAAI,WAAW,GAAG,IAAI,EACtB,kGAQG,sBAAsB;;;cAuC1B,CAAA"}

@@ -24,3 +24,3 @@ import { createAppState } from "../app-state.js";

*/
var createApiClientApp = async (el, { layout = "desktop", plugins, customThemes, fallbackThemeSlug, fetchRegistryDocument, telemetry = true }) => {
var createApiClientApp = async (el, { layout = "desktop", plugins, customThemes, fallbackThemeSlug, fetchRegistryDocument, telemetry = true, options }) => {
const router = createAppRouter(layout);

@@ -31,3 +31,4 @@ const state = await createAppState({

fallbackThemeSlug,
telemetryDefault: telemetry
telemetryDefault: telemetry,
options
});

@@ -34,0 +35,0 @@ const commandPaletteState = useCommandPaletteState();

@@ -1,1 +0,1 @@

{"version":3,"file":"create-api-client-app.js","names":[],"sources":["../../../../../src/v2/features/app/helpers/create-api-client-app.ts"],"sourcesContent":["import type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport type { Theme } from '@scalar/themes'\nimport { createApp } from 'vue'\nimport { createRouter as createVueRouter, createWebHashHistory, createWebHistory } from 'vue-router'\n\nimport App from '@/v2/features/app/App.vue'\nimport { createAppState } from '@/v2/features/app/app-state'\nimport { ROUTES } from '@/v2/features/app/helpers/routes'\nimport type { ImportDocumentFromRegistry } from '@/v2/types/configuration'\nimport type { ClientLayout } from '@/v2/types/layout'\n\nimport { useCommandPaletteState } from '../../command-palette/hooks/use-command-palette-state'\n\ntype CreateApiClientOptions = {\n /**\n * The layout of the client, limited to web or desktop in app\n * @see {@link ClientLayout}\n *\n * @default 'desktop'\n */\n layout: Exclude<ClientLayout, 'modal'>\n /**\n * Api client plugins to include in the app\n */\n plugins?: ClientPlugin[]\n /**\n * Custom themes to include in the app\n */\n customThemes?: Theme[]\n /**\n * Fallback theme slug to use if no theme is selected for the workspace\n * @default 'default'\n */\n fallbackThemeSlug?: () => string\n /**\n * Fetches the full document from registry by meta. When set, registry meta takes priority\n * over x-scalar-original-source-url when syncing. Returns the document as a plain object.\n */\n fetchRegistryDocument?: ImportDocumentFromRegistry\n /**\n * Whether or not to send telemetry events.\n */\n telemetry?: boolean\n}\n\n/**\n * Creates the appropriate router with the appropriate routes based on the layout\n */\nexport const createAppRouter = (layout: CreateApiClientOptions['layout']) => {\n // Web uses the standard HTML5 history API\n if (layout === 'web') {\n return createVueRouter({ history: createWebHistory(), routes: ROUTES })\n }\n\n // Electron app has to use the webHashHistory due to file routing\n return createVueRouter({ history: createWebHashHistory(), routes: ROUTES })\n}\n\n/**\n * Create the API Client with router and passes in the workspace store as a prop\n */\nexport const createApiClientApp = async (\n el: HTMLElement | null,\n {\n layout = 'desktop',\n plugins,\n customThemes,\n fallbackThemeSlug,\n fetchRegistryDocument,\n telemetry = true,\n }: CreateApiClientOptions,\n) => {\n // Add the router\n const router = createAppRouter(layout)\n const state = await createAppState({\n router,\n customThemes,\n fallbackThemeSlug,\n telemetryDefault: telemetry,\n })\n const commandPaletteState = useCommandPaletteState()\n\n // Pass in our initial props at the top level\n const app = createApp(App, {\n layout,\n plugins,\n getAppState: () => state,\n getCommandPaletteState: () => commandPaletteState,\n fetchRegistryDocument,\n })\n app.use(router)\n\n // Mount the vue app\n if (!el) {\n console.error(\n '[@scalar/api-client-modal] Could not create the API client.',\n 'Invalid HTML element provided.',\n 'Read more: https://github.com/scalar/scalar/tree/main/packages/api-client',\n )\n\n return\n }\n app.mount(el)\n\n return {\n app,\n state,\n }\n}\n"],"mappings":";;;;;;;;;;AAgDA,IAAa,mBAAmB,WAA6C;AAE3E,KAAI,WAAW,MACb,QAAO,aAAgB;EAAE,SAAS,kBAAkB;EAAE,QAAQ;EAAQ,CAAC;AAIzE,QAAO,aAAgB;EAAE,SAAS,sBAAsB;EAAE,QAAQ;EAAQ,CAAC;;;;;AAM7E,IAAa,qBAAqB,OAChC,IACA,EACE,SAAS,WACT,SACA,cACA,mBACA,uBACA,YAAY,WAEX;CAEH,MAAM,SAAS,gBAAgB,OAAO;CACtC,MAAM,QAAQ,MAAM,eAAe;EACjC;EACA;EACA;EACA,kBAAkB;EACnB,CAAC;CACF,MAAM,sBAAsB,wBAAwB;CAGpD,MAAM,MAAM,UAAU,aAAK;EACzB;EACA;EACA,mBAAmB;EACnB,8BAA8B;EAC9B;EACD,CAAC;AACF,KAAI,IAAI,OAAO;AAGf,KAAI,CAAC,IAAI;AACP,UAAQ,MACN,+DACA,kCACA,4EACD;AAED;;AAEF,KAAI,MAAM,GAAG;AAEb,QAAO;EACL;EACA;EACD"}
{"version":3,"file":"create-api-client-app.js","names":[],"sources":["../../../../../src/v2/features/app/helpers/create-api-client-app.ts"],"sourcesContent":["import type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport type { Theme } from '@scalar/themes'\nimport { createApp } from 'vue'\nimport { createRouter as createVueRouter, createWebHashHistory, createWebHistory } from 'vue-router'\n\nimport App from '@/v2/features/app/App.vue'\nimport { createAppState } from '@/v2/features/app/app-state'\nimport { ROUTES } from '@/v2/features/app/helpers/routes'\nimport type { ImportDocumentFromRegistry } from '@/v2/types/configuration'\nimport type { ClientLayout } from '@/v2/types/layout'\nimport type { ApiClientOptions } from '@/v2/types/options'\n\nimport { useCommandPaletteState } from '../../command-palette/hooks/use-command-palette-state'\n\ntype CreateApiClientOptions = {\n /**\n * The layout of the client, limited to web or desktop in app\n * @see {@link ClientLayout}\n *\n * @default 'desktop'\n */\n layout: Exclude<ClientLayout, 'modal'>\n /**\n * Api client plugins to include in the app\n */\n plugins?: ClientPlugin[]\n /**\n * Custom themes to include in the app\n */\n customThemes?: Theme[]\n /**\n * Fallback theme slug to use if no theme is selected for the workspace\n * @default 'default'\n */\n fallbackThemeSlug?: () => string\n /**\n * Fetches the full document from registry by meta. When set, registry meta takes priority\n * over x-scalar-original-source-url when syncing. Returns the document as a plain object.\n */\n fetchRegistryDocument?: ImportDocumentFromRegistry\n /**\n * Whether or not to send telemetry events.\n */\n telemetry?: boolean\n /** Runtime behaviour overrides */\n options?: ApiClientAppOptions\n}\n\n/**\n * Runtime behaviour overrides shared between createApiClientApp and createAppState.\n * Derived from the canonical ApiClientOptions to guarantee structural compatibility.\n */\nexport type ApiClientAppOptions = Pick<ApiClientOptions, 'customFetch' | 'oauth2RedirectUri'>\n\n/**\n * Creates the appropriate router with the appropriate routes based on the layout\n */\nexport const createAppRouter = (layout: CreateApiClientOptions['layout']) => {\n // Web uses the standard HTML5 history API\n if (layout === 'web') {\n return createVueRouter({ history: createWebHistory(), routes: ROUTES })\n }\n\n // Electron app has to use the webHashHistory due to file routing\n return createVueRouter({ history: createWebHashHistory(), routes: ROUTES })\n}\n\n/**\n * Create the API Client with router and passes in the workspace store as a prop\n */\nexport const createApiClientApp = async (\n el: HTMLElement | null,\n {\n layout = 'desktop',\n plugins,\n customThemes,\n fallbackThemeSlug,\n fetchRegistryDocument,\n telemetry = true,\n options,\n }: CreateApiClientOptions,\n) => {\n // Add the router\n const router = createAppRouter(layout)\n const state = await createAppState({\n router,\n customThemes,\n fallbackThemeSlug,\n telemetryDefault: telemetry,\n options,\n })\n const commandPaletteState = useCommandPaletteState()\n\n // Pass in our initial props at the top level\n const app = createApp(App, {\n layout,\n plugins,\n getAppState: () => state,\n getCommandPaletteState: () => commandPaletteState,\n fetchRegistryDocument,\n })\n app.use(router)\n\n // Mount the vue app\n if (!el) {\n console.error(\n '[@scalar/api-client-modal] Could not create the API client.',\n 'Invalid HTML element provided.',\n 'Read more: https://github.com/scalar/scalar/tree/main/packages/api-client',\n )\n\n return\n }\n app.mount(el)\n\n return {\n app,\n state,\n }\n}\n"],"mappings":";;;;;;;;;;AAyDA,IAAa,mBAAmB,WAA6C;AAE3E,KAAI,WAAW,MACb,QAAO,aAAgB;EAAE,SAAS,kBAAkB;EAAE,QAAQ;EAAQ,CAAC;AAIzE,QAAO,aAAgB;EAAE,SAAS,sBAAsB;EAAE,QAAQ;EAAQ,CAAC;;;;;AAM7E,IAAa,qBAAqB,OAChC,IACA,EACE,SAAS,WACT,SACA,cACA,mBACA,uBACA,YAAY,MACZ,cAEC;CAEH,MAAM,SAAS,gBAAgB,OAAO;CACtC,MAAM,QAAQ,MAAM,eAAe;EACjC;EACA;EACA;EACA,kBAAkB;EAClB;EACD,CAAC;CACF,MAAM,sBAAsB,wBAAwB;CAGpD,MAAM,MAAM,UAAU,aAAK;EACzB;EACA;EACA,mBAAmB;EACnB,8BAA8B;EAC9B;EACD,CAAC;AACF,KAAI,IAAI,OAAO;AAGf,KAAI,CAAC,IAAI;AACP,UAAQ,MACN,+DACA,kCACA,4EACD;AAED;;AAEF,KAAI,MAAM,GAAG;AAEb,QAAO;EACL;EACA;EACD"}

@@ -8,2 +8,4 @@ import type { HttpMethod } from '@scalar/helpers/http/http-methods';

import type { WorkspaceDocument } from '@scalar/workspace-store/schemas/workspace';
import type { MaybeRefOrGetter } from 'vue';
import type { ApiClientOptions } from '../../../../v2/types/options';
import type { ImportDocumentFromRegistry } from '../../../../v2/types/configuration';

@@ -53,2 +55,4 @@ import type { ClientLayout } from '../../../../v2/types/layout';

onUpdateTelemetry?: (value: boolean) => void;
/** App or modal options forwarded to operation/auth blocks */
options?: MaybeRefOrGetter<ApiClientOptions>;
};

@@ -75,6 +79,4 @@ /** When in the collections pages */

component: import("vue").DefineComponent<RouteProps & {
options?: import("../../modal/helpers/types").ApiClientModalOptionsRef;
requestBodyCompositionSelection?: Record<string, number>;
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<RouteProps & {
options?: import("../../modal/helpers/types").ApiClientModalOptionsRef;
requestBodyCompositionSelection?: Record<string, number>;

@@ -81,0 +83,0 @@ }> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;

@@ -1,1 +0,1 @@

{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/app/helpers/routes.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/app/helpers/routes.ts"],"names":[],"mappings":"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"}

@@ -1,1 +0,1 @@

{"version":3,"file":"routes.js","names":[],"sources":["../../../../../src/v2/features/app/helpers/routes.ts"],"sourcesContent":["import type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport { mergeSearchParams } from '@scalar/helpers/url/merge-urls'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport type { Theme } from '@scalar/themes'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { WorkspaceDocument } from '@scalar/workspace-store/schemas/workspace'\nimport type { RouteRecordRaw } from 'vue-router'\n\nimport Authentication from '@/v2/features/collection/components/Authentication.vue'\nimport Cookies from '@/v2/features/collection/components/Cookies.vue'\nimport { Editor } from '@/v2/features/collection/components/Editor'\nimport Environment from '@/v2/features/collection/components/Environment.vue'\nimport Overview from '@/v2/features/collection/components/Overview.vue'\nimport { Runner } from '@/v2/features/collection/components/Runner'\nimport Servers from '@/v2/features/collection/components/Servers.vue'\nimport Settings from '@/v2/features/collection/components/Settings.vue'\nimport DocumentCollection from '@/v2/features/collection/DocumentCollection.vue'\nimport OperationCollection from '@/v2/features/collection/OperationCollection.vue'\nimport WorkspaceCollection from '@/v2/features/collection/WorkspaceCollection.vue'\nimport { Operation } from '@/v2/features/operation'\nimport { workspaceStorage } from '@/v2/helpers/storage'\nimport type { ImportDocumentFromRegistry } from '@/v2/types/configuration'\nimport type { ClientLayout } from '@/v2/types/layout'\n\n/** These props are provided at the route level */\nexport type RouteProps = {\n /** The slug of the currently selected document in the workspace */\n documentSlug: string\n /** The currently active document */\n document: WorkspaceDocument | null\n /** The workspace event bus */\n eventBus: WorkspaceEventBus\n /** The layout of the client */\n layout: ClientLayout\n /** The API path currently selected (e.g. \"/users/{id}\") */\n path?: string\n /** The HTTP method for the currently selected API path (e.g. GET, POST) */\n method?: HttpMethod\n /** The name of the currently selected example (for examples within an endpoint) */\n exampleName?: string\n /** The currently active environment */\n environment: XScalarEnvironment\n /** The workspace store */\n workspaceStore: WorkspaceStore\n /** The currently active workspace */\n activeWorkspace: { id: string; label: string }\n /** Client plugins */\n plugins: ClientPlugin[]\n /** Custom themes available to the team */\n customThemes?: Theme[]\n /** The currently selected theme styles string */\n currentTheme?: string\n /** Whether the current color mode is dark */\n isDarkMode?: boolean\n /**\n * Fetches the full document from registry by meta. When provided, registry meta takes priority\n * over x-scalar-original-source-url when syncing. Returns the document as a plain object.\n */\n fetchRegistryDocument?: ImportDocumentFromRegistry\n /** Whether telemetry is enabled */\n telemetry?: boolean\n /** Updates the telemetry enabled state */\n onUpdateTelemetry?: (value: boolean) => void\n}\n\n/** When in the collections pages */\nexport type CollectionProps = RouteProps &\n (\n | {\n collectionType: 'document' | 'operation'\n document: WorkspaceDocument\n }\n | {\n collectionType: 'workspace'\n document: null\n }\n )\n\nexport type ScalarClientAppRouteParams =\n | 'namespace'\n | 'workspaceSlug'\n | 'documentSlug'\n | 'pathEncoded'\n | 'method'\n | 'exampleName'\n\n/** Routes for the API client app and web, the same as modal + workspace routes */\nexport const ROUTES = [\n {\n path: '/@:namespace/:workspaceSlug',\n children: [\n {\n path: 'document/:documentSlug',\n children: [\n // Example page\n {\n path: 'path/:pathEncoded/method/:method',\n children: [\n {\n name: 'example',\n path: 'example/:exampleName',\n component: Operation,\n },\n {\n name: 'operation',\n path: '',\n component: OperationCollection,\n redirect: {\n name: 'operation.overview',\n },\n children: [\n {\n name: 'operation.overview',\n path: 'overview',\n component: Overview,\n },\n {\n name: 'operation.servers',\n path: 'servers',\n component: Servers,\n },\n {\n name: 'operation.authentication',\n path: 'authentication',\n component: Authentication,\n },\n {\n name: 'operation.editor',\n path: 'editor',\n component: Editor,\n },\n ],\n },\n ],\n },\n // Document Page\n {\n name: 'document',\n path: '',\n component: DocumentCollection,\n children: [\n // Redirect to overview\n {\n name: 'document.redirect',\n path: '',\n redirect: {\n name: 'document.overview',\n },\n },\n // Document overview\n {\n name: 'document.overview',\n path: 'overview',\n component: Overview,\n },\n // Document servers\n {\n name: 'document.servers',\n path: 'servers',\n component: Servers,\n },\n // Document environment\n {\n name: 'document.environment',\n path: 'environment',\n component: Environment,\n },\n // Document authentication\n {\n name: 'document.authentication',\n path: 'authentication',\n component: Authentication,\n },\n // Document cookies\n {\n name: 'document.cookies',\n path: 'cookies',\n component: Cookies,\n },\n // Document scripts (pre-request / post-response)\n {\n name: 'document.scripts',\n path: 'scripts',\n component: () => import('@/v2/features/collection/components/Scripts.vue'),\n },\n // Document runner\n {\n name: 'document.runner',\n path: 'runner',\n component: Runner,\n },\n // Document settings\n {\n name: 'document.settings',\n path: 'settings',\n component: Settings,\n },\n ],\n },\n ],\n },\n // Workspace page\n {\n name: 'workspace',\n path: '',\n component: WorkspaceCollection,\n children: [\n // Workspace environment\n {\n name: 'workspace.environment',\n path: 'environment',\n component: Environment,\n },\n // Workspace cookies\n {\n name: 'workspace.cookies',\n path: 'cookies',\n component: Cookies,\n },\n // Workspace settings\n {\n name: 'workspace.settings',\n path: 'settings',\n component: Settings,\n },\n ],\n },\n ],\n },\n {\n path: '/:pathMatch(.*)*',\n redirect: () => {\n const DEFAULT_PATH = '/@local/default/document/drafts/overview'\n const lastPath = workspaceStorage.getLastPath() ?? DEFAULT_PATH\n\n // Set the default path to the last path so we don't go to an inifite loop if the last path is invalid\n workspaceStorage.setCurrentPath(DEFAULT_PATH)\n\n const url = new URL(lastPath, 'http://example.com')\n\n const queryParameters = new URLSearchParams(window.location.search)\n\n //Merge the query parameters with the last path\n const mergedSearchParams = mergeSearchParams(url.searchParams, queryParameters)\n\n // Preserve all query paramters\n return `${url.pathname}?${mergedSearchParams.toString()}`\n },\n },\n] satisfies RouteRecordRaw[]\n"],"mappings":";;;;;;;;;;;;;;;;AAyFA,IAAa,SAAS,CACpB;CACE,MAAM;CACN,UAAU,CACR;EACE,MAAM;EACN,UAAU,CAER;GACE,MAAM;GACN,UAAU,CACR;IACE,MAAM;IACN,MAAM;IACN,WAAW;IACZ,EACD;IACE,MAAM;IACN,MAAM;IACN,WAAW;IACX,UAAU,EACR,MAAM,sBACP;IACD,UAAU;KACR;MACE,MAAM;MACN,MAAM;MACN,WAAW;MACZ;KACD;MACE,MAAM;MACN,MAAM;MACN,WAAW;MACZ;KACD;MACE,MAAM;MACN,MAAM;MACN,WAAW;MACZ;KACD;MACE,MAAM;MACN,MAAM;MACN,WAAW;MACZ;KACF;IACF,CACF;GACF,EAED;GACE,MAAM;GACN,MAAM;GACN,WAAW;GACX,UAAU;IAER;KACE,MAAM;KACN,MAAM;KACN,UAAU,EACR,MAAM,qBACP;KACF;IAED;KACE,MAAM;KACN,MAAM;KACN,WAAW;KACZ;IAED;KACE,MAAM;KACN,MAAM;KACN,WAAW;KACZ;IAED;KACE,MAAM;KACN,MAAM;KACN,WAAW;KACZ;IAED;KACE,MAAM;KACN,MAAM;KACN,WAAW;KACZ;IAED;KACE,MAAM;KACN,MAAM;KACN,WAAW;KACZ;IAED;KACE,MAAM;KACN,MAAM;KACN,iBAAiB,OAAO;KACzB;IAED;KACE,MAAM;KACN,MAAM;KACN,WAAW;KACZ;IAED;KACE,MAAM;KACN,MAAM;KACN,WAAW;KACZ;IACF;GACF,CACF;EACF,EAED;EACE,MAAM;EACN,MAAM;EACN,WAAW;EACX,UAAU;GAER;IACE,MAAM;IACN,MAAM;IACN,WAAW;IACZ;GAED;IACE,MAAM;IACN,MAAM;IACN,WAAW;IACZ;GAED;IACE,MAAM;IACN,MAAM;IACN,WAAW;IACZ;GACF;EACF,CACF;CACF,EACD;CACE,MAAM;CACN,gBAAgB;EACd,MAAM,eAAe;EACrB,MAAM,WAAW,iBAAiB,aAAa,IAAI;AAGnD,mBAAiB,eAAe,aAAa;EAE7C,MAAM,MAAM,IAAI,IAAI,UAAU,qBAAqB;EAEnD,MAAM,kBAAkB,IAAI,gBAAgB,OAAO,SAAS,OAAO;EAGnE,MAAM,qBAAqB,kBAAkB,IAAI,cAAc,gBAAgB;AAG/E,SAAO,GAAG,IAAI,SAAS,GAAG,mBAAmB,UAAU;;CAE1D,CACF"}
{"version":3,"file":"routes.js","names":[],"sources":["../../../../../src/v2/features/app/helpers/routes.ts"],"sourcesContent":["import type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport { mergeSearchParams } from '@scalar/helpers/url/merge-urls'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport type { Theme } from '@scalar/themes'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport type { WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport type { WorkspaceDocument } from '@scalar/workspace-store/schemas/workspace'\nimport type { MaybeRefOrGetter } from 'vue'\nimport type { RouteRecordRaw } from 'vue-router'\n\nimport Authentication from '@/v2/features/collection/components/Authentication.vue'\nimport Cookies from '@/v2/features/collection/components/Cookies.vue'\nimport { Editor } from '@/v2/features/collection/components/Editor'\nimport Environment from '@/v2/features/collection/components/Environment.vue'\nimport Overview from '@/v2/features/collection/components/Overview.vue'\nimport { Runner } from '@/v2/features/collection/components/Runner'\nimport Servers from '@/v2/features/collection/components/Servers.vue'\nimport Settings from '@/v2/features/collection/components/Settings.vue'\nimport DocumentCollection from '@/v2/features/collection/DocumentCollection.vue'\nimport OperationCollection from '@/v2/features/collection/OperationCollection.vue'\nimport WorkspaceCollection from '@/v2/features/collection/WorkspaceCollection.vue'\nimport type { ApiClientOptions } from '@/v2/types/options'\nimport { Operation } from '@/v2/features/operation'\nimport { workspaceStorage } from '@/v2/helpers/storage'\nimport type { ImportDocumentFromRegistry } from '@/v2/types/configuration'\nimport type { ClientLayout } from '@/v2/types/layout'\n\n/** These props are provided at the route level */\nexport type RouteProps = {\n /** The slug of the currently selected document in the workspace */\n documentSlug: string\n /** The currently active document */\n document: WorkspaceDocument | null\n /** The workspace event bus */\n eventBus: WorkspaceEventBus\n /** The layout of the client */\n layout: ClientLayout\n /** The API path currently selected (e.g. \"/users/{id}\") */\n path?: string\n /** The HTTP method for the currently selected API path (e.g. GET, POST) */\n method?: HttpMethod\n /** The name of the currently selected example (for examples within an endpoint) */\n exampleName?: string\n /** The currently active environment */\n environment: XScalarEnvironment\n /** The workspace store */\n workspaceStore: WorkspaceStore\n /** The currently active workspace */\n activeWorkspace: { id: string; label: string }\n /** Client plugins */\n plugins: ClientPlugin[]\n /** Custom themes available to the team */\n customThemes?: Theme[]\n /** The currently selected theme styles string */\n currentTheme?: string\n /** Whether the current color mode is dark */\n isDarkMode?: boolean\n /**\n * Fetches the full document from registry by meta. When provided, registry meta takes priority\n * over x-scalar-original-source-url when syncing. Returns the document as a plain object.\n */\n fetchRegistryDocument?: ImportDocumentFromRegistry\n /** Whether telemetry is enabled */\n telemetry?: boolean\n /** Updates the telemetry enabled state */\n onUpdateTelemetry?: (value: boolean) => void\n /** App or modal options forwarded to operation/auth blocks */\n options?: MaybeRefOrGetter<ApiClientOptions>\n}\n\n/** When in the collections pages */\nexport type CollectionProps = RouteProps &\n (\n | {\n collectionType: 'document' | 'operation'\n document: WorkspaceDocument\n }\n | {\n collectionType: 'workspace'\n document: null\n }\n )\n\nexport type ScalarClientAppRouteParams =\n | 'namespace'\n | 'workspaceSlug'\n | 'documentSlug'\n | 'pathEncoded'\n | 'method'\n | 'exampleName'\n\n/** Routes for the API client app and web, the same as modal + workspace routes */\nexport const ROUTES = [\n {\n path: '/@:namespace/:workspaceSlug',\n children: [\n {\n path: 'document/:documentSlug',\n children: [\n // Example page\n {\n path: 'path/:pathEncoded/method/:method',\n children: [\n {\n name: 'example',\n path: 'example/:exampleName',\n component: Operation,\n },\n {\n name: 'operation',\n path: '',\n component: OperationCollection,\n redirect: {\n name: 'operation.overview',\n },\n children: [\n {\n name: 'operation.overview',\n path: 'overview',\n component: Overview,\n },\n {\n name: 'operation.servers',\n path: 'servers',\n component: Servers,\n },\n {\n name: 'operation.authentication',\n path: 'authentication',\n component: Authentication,\n },\n {\n name: 'operation.editor',\n path: 'editor',\n component: Editor,\n },\n ],\n },\n ],\n },\n // Document Page\n {\n name: 'document',\n path: '',\n component: DocumentCollection,\n children: [\n // Redirect to overview\n {\n name: 'document.redirect',\n path: '',\n redirect: {\n name: 'document.overview',\n },\n },\n // Document overview\n {\n name: 'document.overview',\n path: 'overview',\n component: Overview,\n },\n // Document servers\n {\n name: 'document.servers',\n path: 'servers',\n component: Servers,\n },\n // Document environment\n {\n name: 'document.environment',\n path: 'environment',\n component: Environment,\n },\n // Document authentication\n {\n name: 'document.authentication',\n path: 'authentication',\n component: Authentication,\n },\n // Document cookies\n {\n name: 'document.cookies',\n path: 'cookies',\n component: Cookies,\n },\n // Document scripts (pre-request / post-response)\n {\n name: 'document.scripts',\n path: 'scripts',\n component: () => import('@/v2/features/collection/components/Scripts.vue'),\n },\n // Document runner\n {\n name: 'document.runner',\n path: 'runner',\n component: Runner,\n },\n // Document settings\n {\n name: 'document.settings',\n path: 'settings',\n component: Settings,\n },\n ],\n },\n ],\n },\n // Workspace page\n {\n name: 'workspace',\n path: '',\n component: WorkspaceCollection,\n children: [\n // Workspace environment\n {\n name: 'workspace.environment',\n path: 'environment',\n component: Environment,\n },\n // Workspace cookies\n {\n name: 'workspace.cookies',\n path: 'cookies',\n component: Cookies,\n },\n // Workspace settings\n {\n name: 'workspace.settings',\n path: 'settings',\n component: Settings,\n },\n ],\n },\n ],\n },\n {\n path: '/:pathMatch(.*)*',\n redirect: () => {\n const DEFAULT_PATH = '/@local/default/document/drafts/overview'\n const lastPath = workspaceStorage.getLastPath() ?? DEFAULT_PATH\n\n // Set the default path to the last path so we don't go to an inifite loop if the last path is invalid\n workspaceStorage.setCurrentPath(DEFAULT_PATH)\n\n const url = new URL(lastPath, 'http://example.com')\n\n const queryParameters = new URLSearchParams(window.location.search)\n\n //Merge the query parameters with the last path\n const mergedSearchParams = mergeSearchParams(url.searchParams, queryParameters)\n\n // Preserve all query paramters\n return `${url.pathname}?${mergedSearchParams.toString()}`\n },\n },\n] satisfies RouteRecordRaw[]\n"],"mappings":";;;;;;;;;;;;;;;;AA6FA,IAAa,SAAS,CACpB;CACE,MAAM;CACN,UAAU,CACR;EACE,MAAM;EACN,UAAU,CAER;GACE,MAAM;GACN,UAAU,CACR;IACE,MAAM;IACN,MAAM;IACN,WAAW;IACZ,EACD;IACE,MAAM;IACN,MAAM;IACN,WAAW;IACX,UAAU,EACR,MAAM,sBACP;IACD,UAAU;KACR;MACE,MAAM;MACN,MAAM;MACN,WAAW;MACZ;KACD;MACE,MAAM;MACN,MAAM;MACN,WAAW;MACZ;KACD;MACE,MAAM;MACN,MAAM;MACN,WAAW;MACZ;KACD;MACE,MAAM;MACN,MAAM;MACN,WAAW;MACZ;KACF;IACF,CACF;GACF,EAED;GACE,MAAM;GACN,MAAM;GACN,WAAW;GACX,UAAU;IAER;KACE,MAAM;KACN,MAAM;KACN,UAAU,EACR,MAAM,qBACP;KACF;IAED;KACE,MAAM;KACN,MAAM;KACN,WAAW;KACZ;IAED;KACE,MAAM;KACN,MAAM;KACN,WAAW;KACZ;IAED;KACE,MAAM;KACN,MAAM;KACN,WAAW;KACZ;IAED;KACE,MAAM;KACN,MAAM;KACN,WAAW;KACZ;IAED;KACE,MAAM;KACN,MAAM;KACN,WAAW;KACZ;IAED;KACE,MAAM;KACN,MAAM;KACN,iBAAiB,OAAO;KACzB;IAED;KACE,MAAM;KACN,MAAM;KACN,WAAW;KACZ;IAED;KACE,MAAM;KACN,MAAM;KACN,WAAW;KACZ;IACF;GACF,CACF;EACF,EAED;EACE,MAAM;EACN,MAAM;EACN,WAAW;EACX,UAAU;GAER;IACE,MAAM;IACN,MAAM;IACN,WAAW;IACZ;GAED;IACE,MAAM;IACN,MAAM;IACN,WAAW;IACZ;GAED;IACE,MAAM;IACN,MAAM;IACN,WAAW;IACZ;GACF;EACF,CACF;CACF,EACD;CACE,MAAM;CACN,gBAAgB;EACd,MAAM,eAAe;EACrB,MAAM,WAAW,iBAAiB,aAAa,IAAI;AAGnD,mBAAiB,eAAe,aAAa;EAE7C,MAAM,MAAM,IAAI,IAAI,UAAU,qBAAqB;EAEnD,MAAM,kBAAkB,IAAI,gBAAgB,OAAO,SAAS,OAAO;EAGnE,MAAM,qBAAqB,kBAAkB,IAAI,cAAc,gBAAgB;AAG/E,SAAO,GAAG,IAAI,SAAS,GAAG,mBAAmB,UAAU;;CAE1D,CACF"}

@@ -1,1 +0,1 @@

{"version":3,"file":"Authentication.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/collection/components/Authentication.vue"],"names":[],"mappings":"AA+jBA,QAAA,MAAM,YAAY;;;;;;;;;;;;kGAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
{"version":3,"file":"Authentication.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/collection/components/Authentication.vue"],"names":[],"mappings":"AA+lBA,QAAA,MAAM,YAAY;;;;;;;;;;;;kGAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}

@@ -5,3 +5,3 @@ import _plugin_vue_export_helper_default from "../../../../_virtual/_plugin-vue_export-helper.js";

//#region src/v2/features/collection/components/Authentication.vue
var Authentication_default = /* @__PURE__ */ _plugin_vue_export_helper_default(Authentication_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-6bba6b78"]]);
var Authentication_default = /* @__PURE__ */ _plugin_vue_export_helper_default(Authentication_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-d3bc49bd"]]);
//#endregion

@@ -8,0 +8,0 @@ export { Authentication_default as default };

@@ -1,1 +0,1 @@

{"version":3,"file":"Authentication.vue.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Authentication.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarToggle } from '@scalar/components'\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport type { AuthMeta } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport {\n getActiveProxyUrl,\n getSelectedSecurity,\n getServers,\n mergeSecurity,\n} from '@scalar/workspace-store/request-example'\nimport { computed, ref, watchEffect } from 'vue'\n\nimport { AuthSelector } from '@/v2/blocks/scalar-auth-selector-block'\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { getDefaultOperationSecurityToggle } from '@/v2/features/collection/helpers/get-default-operation-security-toggle'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nconst {\n document,\n eventBus,\n environment,\n workspaceStore,\n documentSlug,\n path,\n method,\n collectionType,\n layout,\n} = defineProps<CollectionProps>()\n\n/**\n * Compute the authentication metadata based on the current collection type.\n * If we're working with an operation, include its path and method; otherwise, use the document scope.\n */\nconst authMeta = computed<AuthMeta>(() => {\n if (collectionType === 'operation') {\n return {\n type: 'operation',\n path: path ?? '',\n method: method ?? 'get',\n }\n }\n return { type: 'document' }\n})\n\n/**\n * Compute the operation object based on the current collection type.\n */\nconst operation = computed(() => {\n if (collectionType === 'operation') {\n // Operation not found\n if (!path || !isHttpMethod(method)) {\n return null\n }\n // Operation found, return the servers\n return getResolvedRef(document?.paths?.[path]?.[method])\n }\n return null\n})\n\n/**\n * If enabled we use/set the selected security schemes on the operation level\n */\nconst useOperationSecurity = ref(false)\nwatchEffect(() => {\n useOperationSecurity.value = getDefaultOperationSecurityToggle({\n authStore: workspaceStore.auth,\n documentName: documentSlug,\n ...authMeta.value,\n })\n})\n\nconst securitySchemes = computed(() =>\n mergeSecurity(\n document?.components?.securitySchemes ?? {},\n {},\n workspaceStore.auth,\n documentSlug,\n ),\n)\n\n/** Resolved selected security for the current collection (operation or document), with defaults applied */\nconst selectedSecurity = computed(() => {\n if (collectionType === 'operation') {\n const fromStore = workspaceStore.auth.getAuthSelectedSchemas({\n type: 'operation',\n documentName: documentSlug,\n path: path ?? '',\n method: method ?? 'get',\n })\n return getSelectedSecurity(\n undefined,\n fromStore,\n operation.value?.security ?? [],\n securitySchemes.value,\n )\n }\n const fromStore = workspaceStore.auth.getAuthSelectedSchemas({\n type: 'document',\n documentName: documentSlug,\n })\n return getSelectedSecurity(\n fromStore,\n undefined,\n document?.security ?? [],\n securitySchemes.value,\n )\n})\n\n/** Compute the security requirements for the operation or document based on the current collection type */\nconst securityRequirements = computed(() => {\n if (collectionType === 'operation') {\n return operation.value?.security ?? []\n }\n return document?.security ?? []\n})\n\n/** Compute the proxy URL for the current layout (for the electron we don't want to use the proxy by default) */\nconst proxyUrl = computed(\n () =>\n getActiveProxyUrl(\n workspaceStore.workspace['x-scalar-active-proxy'],\n layout === 'web' ? 'web' : 'other',\n ) ?? '',\n)\n\nconst servers = computed(() => {\n return getServers(operation.value?.servers ?? document?.servers, {\n documentUrl: document?.['x-scalar-original-source-url'],\n })\n})\n\n/** Grab the currently selected server for relative auth URIs */\nconst server = computed(() => {\n const documentServer = document?.['x-scalar-selected-server']\n const operationServer = operation.value?.['x-scalar-selected-server']\n const selectedServerUrl = operationServer ?? documentServer\n return (\n servers.value.find(({ url }) => url === selectedServerUrl) ??\n servers.value[0] ??\n null\n )\n})\n\n/**\n * Handles toggling operation-level security authentication. (Only for operation collections)\n * When enabled (`value` is true), overrides document-level authentication for the current operation.\n * When disabled (`value` is false), reverts to using document-level authentication instead.\n */\nconst handleToggleOperationSecurity = (value: boolean) => {\n if (authMeta.value.type !== 'operation') {\n return\n }\n\n useOperationSecurity.value = value\n\n if (value) {\n // Use the same resolved selection as the UI; unpack so the event payload is plain objects\n const { selectedSchemes } = selectedSecurity.value\n return eventBus.emit('auth:update:selected-security-schemes', {\n selectedRequirements: unpackProxyObject(selectedSchemes, { depth: 1 }),\n newSchemes: [],\n meta: authMeta.value,\n })\n }\n\n // Clear the operation security so document level authentication is used\n return eventBus.emit('auth:clear:selected-security-schemes', {\n meta: authMeta.value,\n })\n}\n</script>\n\n<template>\n <Section>\n <template #title>Authentication</template>\n <template #description>\n <template v-if=\"collectionType === 'operation'\">\n <span class=\"block\">\n Override authentication for this operation with the toggle.\n </span>\n <span class=\"mt-1 block\">\n <strong>On</strong> — Authentication below applies only to this\n operation.\n </span>\n <span class=\"mt-1 block\">\n <strong>Off</strong> — This operation uses document-level\n authentication from the OpenAPI spec.\n </span>\n </template>\n <template v-else>\n Configure authentication for this document. Selected authentication\n applies to all operations unless overridden at the operation level.\n </template>\n </template>\n <template\n v-if=\"collectionType === 'operation'\"\n #actions>\n <div class=\"flex h-8 items-center\">\n <ScalarToggle\n class=\"w-4\"\n :modelValue=\"useOperationSecurity\"\n @update:modelValue=\"handleToggleOperationSecurity\" />\n </div>\n </template>\n\n <!-- Auth Selector -->\n <div\n :class=\"\n collectionType === 'operation' &&\n !useOperationSecurity &&\n 'cursor-not-allowed'\n \">\n <AuthSelector\n class=\"scalar-collection-auth border-none!\"\n :class=\"\n collectionType === 'operation' &&\n !useOperationSecurity &&\n 'pointer-events-none opacity-50 mix-blend-luminosity'\n \"\n :createAnySecurityScheme=\"true\"\n :environment\n :eventBus=\"eventBus\"\n isStatic\n :meta=\"authMeta\"\n :proxyUrl=\"proxyUrl\"\n :securityRequirements=\"securityRequirements\"\n :securitySchemes\n :selectedSecurity=\"selectedSecurity\"\n :server\n title=\"Authentication\" />\n </div>\n </Section>\n</template>\n<style scoped>\n.scalar-collection-auth {\n border: var(--scalar-border-width) solid var(--scalar-border-color);\n border-radius: var(--scalar-radius-lg);\n overflow: hidden;\n}\n</style>\n"],"mappings":""}
{"version":3,"file":"Authentication.vue.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Authentication.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarToggle } from '@scalar/components'\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport type { AuthMeta } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport {\n getActiveProxyUrl,\n getSelectedSecurity,\n getServers,\n mergeSecurity,\n} from '@scalar/workspace-store/request-example'\nimport { computed, ref, toValue, watchEffect } from 'vue'\n\nimport { AuthSelector } from '@/v2/blocks/scalar-auth-selector-block'\nimport type { OAuth2Options } from '@/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue'\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { getDefaultOperationSecurityToggle } from '@/v2/features/collection/helpers/get-default-operation-security-toggle'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nconst {\n document,\n eventBus,\n environment,\n workspaceStore,\n documentSlug,\n path,\n method,\n collectionType,\n layout,\n options,\n} = defineProps<CollectionProps>()\n\n/**\n * Compute the authentication metadata based on the current collection type.\n * If we're working with an operation, include its path and method; otherwise, use the document scope.\n */\nconst authMeta = computed<AuthMeta>(() => {\n if (collectionType === 'operation') {\n return {\n type: 'operation',\n path: path ?? '',\n method: method ?? 'get',\n }\n }\n return { type: 'document' }\n})\n\n/**\n * Compute the operation object based on the current collection type.\n */\nconst operation = computed(() => {\n if (collectionType === 'operation') {\n // Operation not found\n if (!path || !isHttpMethod(method)) {\n return null\n }\n // Operation found, return the servers\n return getResolvedRef(document?.paths?.[path]?.[method])\n }\n return null\n})\n\n/**\n * If enabled we use/set the selected security schemes on the operation level\n */\nconst useOperationSecurity = ref(false)\nwatchEffect(() => {\n useOperationSecurity.value = getDefaultOperationSecurityToggle({\n authStore: workspaceStore.auth,\n documentName: documentSlug,\n ...authMeta.value,\n })\n})\n\nconst securitySchemes = computed(() =>\n mergeSecurity(\n document?.components?.securitySchemes ?? {},\n {},\n workspaceStore.auth,\n documentSlug,\n ),\n)\n\n/** Resolved selected security for the current collection (operation or document), with defaults applied */\nconst selectedSecurity = computed(() => {\n if (collectionType === 'operation') {\n const fromStore = workspaceStore.auth.getAuthSelectedSchemas({\n type: 'operation',\n documentName: documentSlug,\n path: path ?? '',\n method: method ?? 'get',\n })\n return getSelectedSecurity(\n undefined,\n fromStore,\n operation.value?.security ?? [],\n securitySchemes.value,\n )\n }\n const fromStore = workspaceStore.auth.getAuthSelectedSchemas({\n type: 'document',\n documentName: documentSlug,\n })\n return getSelectedSecurity(\n fromStore,\n undefined,\n document?.security ?? [],\n securitySchemes.value,\n )\n})\n\n/** Compute the security requirements for the operation or document based on the current collection type */\nconst securityRequirements = computed(() => {\n if (collectionType === 'operation') {\n return operation.value?.security ?? []\n }\n return document?.security ?? []\n})\n\n/** Compute the proxy URL for the current layout (for the electron we don't want to use the proxy by default) */\nconst proxyUrl = computed(\n () =>\n getActiveProxyUrl(\n workspaceStore.workspace['x-scalar-active-proxy'],\n layout === 'web' ? 'web' : 'other',\n ) ?? '',\n)\n\nconst servers = computed(() => {\n return getServers(operation.value?.servers ?? document?.servers, {\n documentUrl: document?.['x-scalar-original-source-url'],\n })\n})\n\n/** Grab the currently selected server for relative auth URIs */\nconst server = computed(() => {\n const documentServer = document?.['x-scalar-selected-server']\n const operationServer = operation.value?.['x-scalar-selected-server']\n const selectedServerUrl = operationServer ?? documentServer\n return (\n servers.value.find(({ url }) => url === selectedServerUrl) ??\n servers.value[0] ??\n null\n )\n})\n\n/** Auth selector only needs OAuth2-specific option overrides. */\nconst authOptions = computed<OAuth2Options | undefined>(() => {\n const routeOptions = toValue(options)\n if (!routeOptions?.oauth2RedirectUri) {\n return undefined\n }\n\n return {\n oauth2RedirectUri: routeOptions.oauth2RedirectUri,\n }\n})\n\n/**\n * Handles toggling operation-level security authentication. (Only for operation collections)\n * When enabled (`value` is true), overrides document-level authentication for the current operation.\n * When disabled (`value` is false), reverts to using document-level authentication instead.\n */\nconst handleToggleOperationSecurity = (value: boolean) => {\n if (authMeta.value.type !== 'operation') {\n return\n }\n\n useOperationSecurity.value = value\n\n if (value) {\n // Use the same resolved selection as the UI; unpack so the event payload is plain objects\n const { selectedSchemes } = selectedSecurity.value\n return eventBus.emit('auth:update:selected-security-schemes', {\n selectedRequirements: unpackProxyObject(selectedSchemes, { depth: 1 }),\n newSchemes: [],\n meta: authMeta.value,\n })\n }\n\n // Clear the operation security so document level authentication is used\n return eventBus.emit('auth:clear:selected-security-schemes', {\n meta: authMeta.value,\n })\n}\n</script>\n\n<template>\n <Section>\n <template #title>Authentication</template>\n <template #description>\n <template v-if=\"collectionType === 'operation'\">\n <span class=\"block\">\n Override authentication for this operation with the toggle.\n </span>\n <span class=\"mt-1 block\">\n <strong>On</strong> — Authentication below applies only to this\n operation.\n </span>\n <span class=\"mt-1 block\">\n <strong>Off</strong> — This operation uses document-level\n authentication from the OpenAPI spec.\n </span>\n </template>\n <template v-else>\n Configure authentication for this document. Selected authentication\n applies to all operations unless overridden at the operation level.\n </template>\n </template>\n <template\n v-if=\"collectionType === 'operation'\"\n #actions>\n <div class=\"flex h-8 items-center\">\n <ScalarToggle\n class=\"w-4\"\n :modelValue=\"useOperationSecurity\"\n @update:modelValue=\"handleToggleOperationSecurity\" />\n </div>\n </template>\n\n <!-- Auth Selector -->\n <div\n :class=\"\n collectionType === 'operation' &&\n !useOperationSecurity &&\n 'cursor-not-allowed'\n \">\n <AuthSelector\n class=\"scalar-collection-auth border-none!\"\n :class=\"\n collectionType === 'operation' &&\n !useOperationSecurity &&\n 'pointer-events-none opacity-50 mix-blend-luminosity'\n \"\n :createAnySecurityScheme=\"true\"\n :environment\n :eventBus=\"eventBus\"\n isStatic\n :meta=\"authMeta\"\n :options=\"authOptions\"\n :proxyUrl=\"proxyUrl\"\n :securityRequirements=\"securityRequirements\"\n :securitySchemes\n :selectedSecurity=\"selectedSecurity\"\n :server\n title=\"Authentication\" />\n </div>\n </Section>\n</template>\n<style scoped>\n.scalar-collection-auth {\n border: var(--scalar-border-width) solid var(--scalar-border-color);\n border-radius: var(--scalar-radius-lg);\n overflow: hidden;\n}\n</style>\n"],"mappings":""}
import AuthSelector_default from "../../../blocks/scalar-auth-selector-block/components/AuthSelector.vue.js";
import { getDefaultOperationSecurityToggle } from "../helpers/get-default-operation-security-toggle.js";
import Section_default from "../../settings/components/Section.vue.js";
import { Fragment, computed, createBlock, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, normalizeClass, openBlock, ref, unref, watchEffect, withCtx } from "vue";
import { Fragment, computed, createBlock, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, normalizeClass, openBlock, ref, toValue, unref, watchEffect, withCtx } from "vue";
import { ScalarToggle } from "@scalar/components";

@@ -32,2 +32,3 @@ import { getActiveProxyUrl, getSelectedSecurity, getServers, mergeSecurity } from "@scalar/workspace-store/request-example";

onUpdateTelemetry: { type: Function },
options: {},
collectionType: {}

@@ -99,2 +100,8 @@ },

});
/** Auth selector only needs OAuth2-specific option overrides. */
const authOptions = computed(() => {
const routeOptions = toValue(__props.options);
if (!routeOptions?.oauth2RedirectUri) return;
return { oauth2RedirectUri: routeOptions.oauth2RedirectUri };
});
/**

@@ -133,2 +140,3 @@ * Handles toggling operation-level security authentication. (Only for operation collections)

meta: authMeta.value,
options: authOptions.value,
proxyUrl: proxyUrl.value,

@@ -145,2 +153,3 @@ securityRequirements: securityRequirements.value,

"meta",
"options",
"proxyUrl",

@@ -147,0 +156,0 @@ "securityRequirements",

@@ -1,1 +0,1 @@

{"version":3,"file":"Authentication.vue.script.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Authentication.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarToggle } from '@scalar/components'\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport type { AuthMeta } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport {\n getActiveProxyUrl,\n getSelectedSecurity,\n getServers,\n mergeSecurity,\n} from '@scalar/workspace-store/request-example'\nimport { computed, ref, watchEffect } from 'vue'\n\nimport { AuthSelector } from '@/v2/blocks/scalar-auth-selector-block'\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { getDefaultOperationSecurityToggle } from '@/v2/features/collection/helpers/get-default-operation-security-toggle'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nconst {\n document,\n eventBus,\n environment,\n workspaceStore,\n documentSlug,\n path,\n method,\n collectionType,\n layout,\n} = defineProps<CollectionProps>()\n\n/**\n * Compute the authentication metadata based on the current collection type.\n * If we're working with an operation, include its path and method; otherwise, use the document scope.\n */\nconst authMeta = computed<AuthMeta>(() => {\n if (collectionType === 'operation') {\n return {\n type: 'operation',\n path: path ?? '',\n method: method ?? 'get',\n }\n }\n return { type: 'document' }\n})\n\n/**\n * Compute the operation object based on the current collection type.\n */\nconst operation = computed(() => {\n if (collectionType === 'operation') {\n // Operation not found\n if (!path || !isHttpMethod(method)) {\n return null\n }\n // Operation found, return the servers\n return getResolvedRef(document?.paths?.[path]?.[method])\n }\n return null\n})\n\n/**\n * If enabled we use/set the selected security schemes on the operation level\n */\nconst useOperationSecurity = ref(false)\nwatchEffect(() => {\n useOperationSecurity.value = getDefaultOperationSecurityToggle({\n authStore: workspaceStore.auth,\n documentName: documentSlug,\n ...authMeta.value,\n })\n})\n\nconst securitySchemes = computed(() =>\n mergeSecurity(\n document?.components?.securitySchemes ?? {},\n {},\n workspaceStore.auth,\n documentSlug,\n ),\n)\n\n/** Resolved selected security for the current collection (operation or document), with defaults applied */\nconst selectedSecurity = computed(() => {\n if (collectionType === 'operation') {\n const fromStore = workspaceStore.auth.getAuthSelectedSchemas({\n type: 'operation',\n documentName: documentSlug,\n path: path ?? '',\n method: method ?? 'get',\n })\n return getSelectedSecurity(\n undefined,\n fromStore,\n operation.value?.security ?? [],\n securitySchemes.value,\n )\n }\n const fromStore = workspaceStore.auth.getAuthSelectedSchemas({\n type: 'document',\n documentName: documentSlug,\n })\n return getSelectedSecurity(\n fromStore,\n undefined,\n document?.security ?? [],\n securitySchemes.value,\n )\n})\n\n/** Compute the security requirements for the operation or document based on the current collection type */\nconst securityRequirements = computed(() => {\n if (collectionType === 'operation') {\n return operation.value?.security ?? []\n }\n return document?.security ?? []\n})\n\n/** Compute the proxy URL for the current layout (for the electron we don't want to use the proxy by default) */\nconst proxyUrl = computed(\n () =>\n getActiveProxyUrl(\n workspaceStore.workspace['x-scalar-active-proxy'],\n layout === 'web' ? 'web' : 'other',\n ) ?? '',\n)\n\nconst servers = computed(() => {\n return getServers(operation.value?.servers ?? document?.servers, {\n documentUrl: document?.['x-scalar-original-source-url'],\n })\n})\n\n/** Grab the currently selected server for relative auth URIs */\nconst server = computed(() => {\n const documentServer = document?.['x-scalar-selected-server']\n const operationServer = operation.value?.['x-scalar-selected-server']\n const selectedServerUrl = operationServer ?? documentServer\n return (\n servers.value.find(({ url }) => url === selectedServerUrl) ??\n servers.value[0] ??\n null\n )\n})\n\n/**\n * Handles toggling operation-level security authentication. (Only for operation collections)\n * When enabled (`value` is true), overrides document-level authentication for the current operation.\n * When disabled (`value` is false), reverts to using document-level authentication instead.\n */\nconst handleToggleOperationSecurity = (value: boolean) => {\n if (authMeta.value.type !== 'operation') {\n return\n }\n\n useOperationSecurity.value = value\n\n if (value) {\n // Use the same resolved selection as the UI; unpack so the event payload is plain objects\n const { selectedSchemes } = selectedSecurity.value\n return eventBus.emit('auth:update:selected-security-schemes', {\n selectedRequirements: unpackProxyObject(selectedSchemes, { depth: 1 }),\n newSchemes: [],\n meta: authMeta.value,\n })\n }\n\n // Clear the operation security so document level authentication is used\n return eventBus.emit('auth:clear:selected-security-schemes', {\n meta: authMeta.value,\n })\n}\n</script>\n\n<template>\n <Section>\n <template #title>Authentication</template>\n <template #description>\n <template v-if=\"collectionType === 'operation'\">\n <span class=\"block\">\n Override authentication for this operation with the toggle.\n </span>\n <span class=\"mt-1 block\">\n <strong>On</strong> — Authentication below applies only to this\n operation.\n </span>\n <span class=\"mt-1 block\">\n <strong>Off</strong> — This operation uses document-level\n authentication from the OpenAPI spec.\n </span>\n </template>\n <template v-else>\n Configure authentication for this document. Selected authentication\n applies to all operations unless overridden at the operation level.\n </template>\n </template>\n <template\n v-if=\"collectionType === 'operation'\"\n #actions>\n <div class=\"flex h-8 items-center\">\n <ScalarToggle\n class=\"w-4\"\n :modelValue=\"useOperationSecurity\"\n @update:modelValue=\"handleToggleOperationSecurity\" />\n </div>\n </template>\n\n <!-- Auth Selector -->\n <div\n :class=\"\n collectionType === 'operation' &&\n !useOperationSecurity &&\n 'cursor-not-allowed'\n \">\n <AuthSelector\n class=\"scalar-collection-auth border-none!\"\n :class=\"\n collectionType === 'operation' &&\n !useOperationSecurity &&\n 'pointer-events-none opacity-50 mix-blend-luminosity'\n \"\n :createAnySecurityScheme=\"true\"\n :environment\n :eventBus=\"eventBus\"\n isStatic\n :meta=\"authMeta\"\n :proxyUrl=\"proxyUrl\"\n :securityRequirements=\"securityRequirements\"\n :securitySchemes\n :selectedSecurity=\"selectedSecurity\"\n :server\n title=\"Authentication\" />\n </div>\n </Section>\n</template>\n<style scoped>\n.scalar-collection-auth {\n border: var(--scalar-border-width) solid var(--scalar-border-color);\n border-radius: var(--scalar-radius-lg);\n overflow: hidden;\n}\n</style>\n"],"mappings":"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"}
{"version":3,"file":"Authentication.vue.script.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Authentication.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarToggle } from '@scalar/components'\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport type { AuthMeta } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport {\n getActiveProxyUrl,\n getSelectedSecurity,\n getServers,\n mergeSecurity,\n} from '@scalar/workspace-store/request-example'\nimport { computed, ref, toValue, watchEffect } from 'vue'\n\nimport { AuthSelector } from '@/v2/blocks/scalar-auth-selector-block'\nimport type { OAuth2Options } from '@/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue'\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { getDefaultOperationSecurityToggle } from '@/v2/features/collection/helpers/get-default-operation-security-toggle'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nconst {\n document,\n eventBus,\n environment,\n workspaceStore,\n documentSlug,\n path,\n method,\n collectionType,\n layout,\n options,\n} = defineProps<CollectionProps>()\n\n/**\n * Compute the authentication metadata based on the current collection type.\n * If we're working with an operation, include its path and method; otherwise, use the document scope.\n */\nconst authMeta = computed<AuthMeta>(() => {\n if (collectionType === 'operation') {\n return {\n type: 'operation',\n path: path ?? '',\n method: method ?? 'get',\n }\n }\n return { type: 'document' }\n})\n\n/**\n * Compute the operation object based on the current collection type.\n */\nconst operation = computed(() => {\n if (collectionType === 'operation') {\n // Operation not found\n if (!path || !isHttpMethod(method)) {\n return null\n }\n // Operation found, return the servers\n return getResolvedRef(document?.paths?.[path]?.[method])\n }\n return null\n})\n\n/**\n * If enabled we use/set the selected security schemes on the operation level\n */\nconst useOperationSecurity = ref(false)\nwatchEffect(() => {\n useOperationSecurity.value = getDefaultOperationSecurityToggle({\n authStore: workspaceStore.auth,\n documentName: documentSlug,\n ...authMeta.value,\n })\n})\n\nconst securitySchemes = computed(() =>\n mergeSecurity(\n document?.components?.securitySchemes ?? {},\n {},\n workspaceStore.auth,\n documentSlug,\n ),\n)\n\n/** Resolved selected security for the current collection (operation or document), with defaults applied */\nconst selectedSecurity = computed(() => {\n if (collectionType === 'operation') {\n const fromStore = workspaceStore.auth.getAuthSelectedSchemas({\n type: 'operation',\n documentName: documentSlug,\n path: path ?? '',\n method: method ?? 'get',\n })\n return getSelectedSecurity(\n undefined,\n fromStore,\n operation.value?.security ?? [],\n securitySchemes.value,\n )\n }\n const fromStore = workspaceStore.auth.getAuthSelectedSchemas({\n type: 'document',\n documentName: documentSlug,\n })\n return getSelectedSecurity(\n fromStore,\n undefined,\n document?.security ?? [],\n securitySchemes.value,\n )\n})\n\n/** Compute the security requirements for the operation or document based on the current collection type */\nconst securityRequirements = computed(() => {\n if (collectionType === 'operation') {\n return operation.value?.security ?? []\n }\n return document?.security ?? []\n})\n\n/** Compute the proxy URL for the current layout (for the electron we don't want to use the proxy by default) */\nconst proxyUrl = computed(\n () =>\n getActiveProxyUrl(\n workspaceStore.workspace['x-scalar-active-proxy'],\n layout === 'web' ? 'web' : 'other',\n ) ?? '',\n)\n\nconst servers = computed(() => {\n return getServers(operation.value?.servers ?? document?.servers, {\n documentUrl: document?.['x-scalar-original-source-url'],\n })\n})\n\n/** Grab the currently selected server for relative auth URIs */\nconst server = computed(() => {\n const documentServer = document?.['x-scalar-selected-server']\n const operationServer = operation.value?.['x-scalar-selected-server']\n const selectedServerUrl = operationServer ?? documentServer\n return (\n servers.value.find(({ url }) => url === selectedServerUrl) ??\n servers.value[0] ??\n null\n )\n})\n\n/** Auth selector only needs OAuth2-specific option overrides. */\nconst authOptions = computed<OAuth2Options | undefined>(() => {\n const routeOptions = toValue(options)\n if (!routeOptions?.oauth2RedirectUri) {\n return undefined\n }\n\n return {\n oauth2RedirectUri: routeOptions.oauth2RedirectUri,\n }\n})\n\n/**\n * Handles toggling operation-level security authentication. (Only for operation collections)\n * When enabled (`value` is true), overrides document-level authentication for the current operation.\n * When disabled (`value` is false), reverts to using document-level authentication instead.\n */\nconst handleToggleOperationSecurity = (value: boolean) => {\n if (authMeta.value.type !== 'operation') {\n return\n }\n\n useOperationSecurity.value = value\n\n if (value) {\n // Use the same resolved selection as the UI; unpack so the event payload is plain objects\n const { selectedSchemes } = selectedSecurity.value\n return eventBus.emit('auth:update:selected-security-schemes', {\n selectedRequirements: unpackProxyObject(selectedSchemes, { depth: 1 }),\n newSchemes: [],\n meta: authMeta.value,\n })\n }\n\n // Clear the operation security so document level authentication is used\n return eventBus.emit('auth:clear:selected-security-schemes', {\n meta: authMeta.value,\n })\n}\n</script>\n\n<template>\n <Section>\n <template #title>Authentication</template>\n <template #description>\n <template v-if=\"collectionType === 'operation'\">\n <span class=\"block\">\n Override authentication for this operation with the toggle.\n </span>\n <span class=\"mt-1 block\">\n <strong>On</strong> — Authentication below applies only to this\n operation.\n </span>\n <span class=\"mt-1 block\">\n <strong>Off</strong> — This operation uses document-level\n authentication from the OpenAPI spec.\n </span>\n </template>\n <template v-else>\n Configure authentication for this document. Selected authentication\n applies to all operations unless overridden at the operation level.\n </template>\n </template>\n <template\n v-if=\"collectionType === 'operation'\"\n #actions>\n <div class=\"flex h-8 items-center\">\n <ScalarToggle\n class=\"w-4\"\n :modelValue=\"useOperationSecurity\"\n @update:modelValue=\"handleToggleOperationSecurity\" />\n </div>\n </template>\n\n <!-- Auth Selector -->\n <div\n :class=\"\n collectionType === 'operation' &&\n !useOperationSecurity &&\n 'cursor-not-allowed'\n \">\n <AuthSelector\n class=\"scalar-collection-auth border-none!\"\n :class=\"\n collectionType === 'operation' &&\n !useOperationSecurity &&\n 'pointer-events-none opacity-50 mix-blend-luminosity'\n \"\n :createAnySecurityScheme=\"true\"\n :environment\n :eventBus=\"eventBus\"\n isStatic\n :meta=\"authMeta\"\n :options=\"authOptions\"\n :proxyUrl=\"proxyUrl\"\n :securityRequirements=\"securityRequirements\"\n :securitySchemes\n :selectedSecurity=\"selectedSecurity\"\n :server\n title=\"Authentication\" />\n </div>\n </Section>\n</template>\n<style scoped>\n.scalar-collection-auth {\n border: var(--scalar-border-width) solid var(--scalar-border-color);\n border-radius: var(--scalar-radius-lg);\n overflow: hidden;\n}\n</style>\n"],"mappings":"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"}

@@ -24,2 +24,3 @@ import Section_default from "../../settings/components/Section.vue.js";

onUpdateTelemetry: { type: Function },
options: {},
collectionType: {}

@@ -26,0 +27,0 @@ },

@@ -1,1 +0,1 @@

{"version":3,"file":"Cookies.vue.script.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Cookies.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Cookies section for the collection.\n * Renders document or workspace cookies and lets users manage key-value data\n * sent with API requests (e.g. session tokens, auth, preferences).\n */\nexport default {\n name: 'Cookies',\n}\n</script>\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { CookiesTable } from '@/v2/features/global-cookies'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nconst { collectionType, eventBus, document, workspaceStore } =\n defineProps<CollectionProps>()\n\nconst cookies = computed(() => {\n return (\n (collectionType === 'document'\n ? document['x-scalar-cookies']\n : workspaceStore.workspace['x-scalar-cookies']) ?? []\n )\n})\n</script>\n\n<template>\n <Section v-if=\"collectionType !== 'operation'\">\n <template #title>Cookies</template>\n <template #description>\n Manage your collection's cookies here.<br />Cookies allow you to store and\n send key-value data with your API requests—often used for things like\n session tokens, authentication, and saving user preferences.<br />\n </template>\n <CookiesTable\n :collectionType=\"collectionType\"\n :cookies=\"cookies\"\n :eventBus=\"eventBus\" />\n </Section>\n</template>\n"],"mappings":";;;;CAOE,MAAM;;;;;;;;;;;;;;;;;;;;;;EAaR,MAAM,UAAU,eAAe;AAC7B,WACG,QAAA,mBAAmB,aAChB,QAAA,SAAS,sBACT,QAAA,eAAe,UAAU,wBAAwB,EAAC;IAEzD;;UAIgB,QAAA,mBAAc,eAAA,WAAA,EAA7B,YAWU,iBAAA,EAAA,KAAA,GAAA,EAAA;IAVG,OAAK,cAAQ,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAAA,gBAAP,WAAO,GAAA,CAAA,EAAA,CAAA;IACb,aAAW,cACkB,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA;qBADjB,2CACiB,GAAA;KAAA,mBAAM,MAAA,MAAA,MAAA,GAAA;qBAAA,qKAEgB,GAAA;KAAA,mBAAM,MAAA,MAAA,MAAA,GAAA;;2BAK3C,CAHzB,YAGyB,MAAA,qBAAA,EAAA;KAFtB,gBAAgB,QAAA;KAChB,SAAS,QAAA;KACT,UAAU,QAAA"}
{"version":3,"file":"Cookies.vue.script.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Cookies.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Cookies section for the collection.\n * Renders document or workspace cookies and lets users manage key-value data\n * sent with API requests (e.g. session tokens, auth, preferences).\n */\nexport default {\n name: 'Cookies',\n}\n</script>\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { CookiesTable } from '@/v2/features/global-cookies'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nconst { collectionType, eventBus, document, workspaceStore } =\n defineProps<CollectionProps>()\n\nconst cookies = computed(() => {\n return (\n (collectionType === 'document'\n ? document['x-scalar-cookies']\n : workspaceStore.workspace['x-scalar-cookies']) ?? []\n )\n})\n</script>\n\n<template>\n <Section v-if=\"collectionType !== 'operation'\">\n <template #title>Cookies</template>\n <template #description>\n Manage your collection's cookies here.<br />Cookies allow you to store and\n send key-value data with your API requests—often used for things like\n session tokens, authentication, and saving user preferences.<br />\n </template>\n <CookiesTable\n :collectionType=\"collectionType\"\n :cookies=\"cookies\"\n :eventBus=\"eventBus\" />\n </Section>\n</template>\n"],"mappings":";;;;CAOE,MAAM;;;;;;;;;;;;;;;;;;;;;;;EAaR,MAAM,UAAU,eAAe;AAC7B,WACG,QAAA,mBAAmB,aAChB,QAAA,SAAS,sBACT,QAAA,eAAe,UAAU,wBAAwB,EAAC;IAEzD;;UAIgB,QAAA,mBAAc,eAAA,WAAA,EAA7B,YAWU,iBAAA,EAAA,KAAA,GAAA,EAAA;IAVG,OAAK,cAAQ,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAAA,gBAAP,WAAO,GAAA,CAAA,EAAA,CAAA;IACb,aAAW,cACkB,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA;qBADjB,2CACiB,GAAA;KAAA,mBAAM,MAAA,MAAA,MAAA,GAAA;qBAAA,qKAEgB,GAAA;KAAA,mBAAM,MAAA,MAAA,MAAA,GAAA;;2BAK3C,CAHzB,YAGyB,MAAA,qBAAA,EAAA;KAFtB,gBAAgB,QAAA;KAChB,SAAS,QAAA;KACT,UAAU,QAAA"}

@@ -58,2 +58,3 @@ import { useEditor } from "../../../editor/hooks/use-editor.js";

onUpdateTelemetry: { type: Function },
options: {},
collectionType: {}

@@ -60,0 +61,0 @@ },

@@ -1,1 +0,1 @@

{"version":3,"file":"Editor.vue.script.js","names":[],"sources":["../../../../../../src/v2/features/collection/components/Editor/Editor.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton, ScalarHotkey, useLoadingState } from '@scalar/components'\nimport { debounce } from '@scalar/helpers/general/debounce'\nimport { isObject } from '@scalar/helpers/object/is-object'\nimport { ScalarIconArrowsIn, ScalarIconArrowsOut } from '@scalar/icons'\nimport * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js'\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n onMounted,\n ref,\n shallowRef,\n watch,\n} from 'vue'\n\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { useEditor, useJsonPointerLinkSupport } from '@/v2/features/editor'\nimport { createJsonModel } from '@/v2/features/editor/helpers/json/create-json-model'\nimport { createYamlModel } from '@/v2/features/editor/helpers/yaml/create-yaml-model'\nimport { useEditorMarkers } from '@/v2/features/editor/hooks/use-editor-markers'\n\nimport EditorDiagnosticsPanel from './components/EditorDiagnosticsPanel.vue'\nimport EditorSavePanel from './components/EditorSavePanel.vue'\nimport { getDiagnosticCounts } from './helpers/get-diagnostic-counts'\nimport { getOperationContext } from './helpers/get-operation-context'\nimport { getVisibleDiagnostics } from './helpers/get-visible-diagnostics'\nimport { parseEditorObject } from './helpers/parse-editor-object'\nimport { stringifyDocument } from './helpers/stringify-document'\nimport { useEditorState } from './hooks/use-editor-state'\n\nconst { collectionType, documentSlug, method, path, workspaceStore } =\n defineProps<CollectionProps>()\n\nconst MAX_VISIBLE_DIAGNOSTICS = 6\nconst EDITOR_PERSIST_DEBOUNCE_KEY = 'editor:replace-document'\n\nconst monacoEditorRef = ref<HTMLElement>()\nconst editorApi = shallowRef<ReturnType<typeof useEditor>>()\n\nconst saveLoader = useLoadingState()\nconst {\n isAutoSaveEnabled,\n isDirty,\n editorLanguage,\n isDiagnosticsPaneExpanded,\n isEditorMaximized,\n isYamlMode,\n editorBottomPadding,\n editorRootClass,\n getLanguageToggleClass,\n toggleEditorMaximized,\n} = useEditorState()\n\nconst jsonModel = createJsonModel()\nconst yamlModel = createYamlModel()\n\nconst selectedLanguage = ref<'json' | 'yaml'>('json')\n\nconst currentModel = computed(() => {\n return selectedLanguage.value === 'json' ? jsonModel : yamlModel\n})\n\nconst monacoEditorInstance = computed(() => editorApi.value?.editor)\nconst { markers: diagnostics } = useEditorMarkers(monacoEditorInstance)\n\nconst syncEditorBottomPadding = () => {\n editorApi.value?.editor.updateOptions({\n padding: {\n top: 0,\n bottom: editorBottomPadding.value,\n },\n })\n}\n\nconst diagnosticCounts = computed(() => getDiagnosticCounts(diagnostics.value))\nconst visibleDiagnostics = computed(() =>\n getVisibleDiagnostics(diagnostics.value, MAX_VISIBLE_DIAGNOSTICS),\n)\n\nconst focusDiagnostic = (marker: monaco.editor.IMarker) => {\n const editor = editorApi.value?.editor\n if (!editor) {\n return\n }\n editor.setSelection({\n startLineNumber: marker.startLineNumber,\n startColumn: marker.startColumn,\n endLineNumber: marker.endLineNumber,\n endColumn: marker.endColumn,\n })\n editor.revealPositionInCenter({\n lineNumber: marker.startLineNumber,\n column: marker.startColumn,\n })\n}\n\nconst getEditorValue = (): string | null => currentModel.value.model.getValue()\n\n/** Value from the editor for a specific language (use when switching to avoid reading the wrong model). */\nconst getEditorValueForLanguage = (language: 'json' | 'yaml'): string | null =>\n (language === 'json' ? jsonModel : yamlModel).model.getValue()\n\nconst getDocumentValue = async (\n language?: 'json' | 'yaml',\n): Promise<string> => {\n const document = await workspaceStore.getEditableDocument(documentSlug)\n return stringifyDocument(document, language ?? selectedLanguage.value)\n}\n\nconst debouncedPersist = debounce({ delay: 1500 })\n\nconst applyProgrammaticEditorValue = (value: string): void => {\n // Cancel pending auto-save work so synthetic model updates do not persist stale data.\n debouncedPersist.cleanup()\n editorApi.value?.setValue(value, true)\n}\n\nconst loadDocumentIntoEditor = async () => {\n applyProgrammaticEditorValue(await getDocumentValue())\n isDirty.value = false\n await focusOperation()\n}\n\nconst formatDocument = async () => {\n await editorApi.value?.formatDocument()\n}\n\nconst focusOperation = async () => {\n const operationContext = getOperationContext(path, method)\n if (!operationContext) {\n return\n }\n\n await editorApi.value?.focusPath([\n 'paths',\n operationContext.path,\n operationContext.method,\n ])\n}\n\nconst persistEditorToWorkspace = async (value: string) => {\n const parsed = parseEditorObject(value, editorLanguage.value)\n if (!parsed) {\n const firstError = diagnostics.value.find(\n (m) => m.severity === monaco.MarkerSeverity.Error,\n )\n if (firstError) {\n focusDiagnostic(firstError)\n }\n await saveLoader.invalidate()\n return\n }\n\n saveLoader.start()\n await workspaceStore.replaceDocument(documentSlug, parsed)\n isDirty.value = false\n await saveLoader.validate({ duration: 900 })\n}\n\nconst saveNow = async () => {\n const value = getEditorValue()\n if (!value) {\n return\n }\n await persistEditorToWorkspace(value)\n}\n\nconst handleEditorChange = (value: string) => {\n isDirty.value = true\n\n if (!isAutoSaveEnabled.value) {\n return\n }\n\n debouncedPersist.execute(EDITOR_PERSIST_DEBOUNCE_KEY, () =>\n persistEditorToWorkspace(value),\n )\n}\n\nconst focusOperationServers = async () => {\n const operationContext = getOperationContext(path, method)\n if (!operationContext) {\n return\n }\n\n const value = getEditorValue()\n if (!value) {\n return\n }\n\n const parsed = parseEditorObject(value, editorLanguage.value)\n\n if (!parsed || !isObject(parsed.paths)) {\n return\n }\n\n const pathsObject = parsed.paths as Record<string, unknown>\n const operationPathItem = pathsObject[operationContext.path]\n if (!isObject(operationPathItem)) {\n return\n }\n\n const operation = operationPathItem[operationContext.method]\n if (!isObject(operation)) {\n return\n }\n\n // Add default servers if not present\n operation.servers ??= []\n\n // Update the editor value\n editorApi.value?.setValue(stringifyDocument(parsed, editorLanguage.value))\n await editorApi.value?.focusPath([\n 'paths',\n operationContext.path,\n operationContext.method,\n 'servers',\n ])\n}\n\nuseJsonPointerLinkSupport(editorApi, currentModel)\n\nonMounted(() => {\n editorApi.value = useEditor({\n element: monacoEditorRef.value ?? document.createElement('div'),\n onChange: handleEditorChange,\n model: currentModel,\n actions: [\n {\n id: 'scalar.editor.focusOperation',\n label: 'Focus Operation',\n keybindings: [monaco.KeyMod.Alt | monaco.KeyCode.KeyO],\n run: async () => {\n await focusOperation()\n },\n },\n {\n id: 'scalar.editor.focusOperationServers',\n label: 'Focus Operation Servers',\n keybindings: [monaco.KeyMod.Alt | monaco.KeyCode.KeyS],\n run: async () => {\n await focusOperationServers()\n },\n },\n {\n id: 'scalar.editor.formatDocument',\n label: 'Format Document',\n keybindings: [\n monaco.KeyMod.Alt | monaco.KeyMod.Shift | monaco.KeyCode.KeyF,\n ],\n run: async () => {\n await formatDocument()\n },\n },\n ],\n })\n\n syncEditorBottomPadding()\n void loadDocumentIntoEditor()\n})\n\nonBeforeUnmount(() => {\n debouncedPersist.cleanup()\n\n // Persist if there is a pending save\n if (isDirty.value && isAutoSaveEnabled.value) {\n void saveNow()\n }\n editorApi.value?.dispose?.()\n // Dispose models created at setup; useEditor only disposes the editor widget, not external models.\n jsonModel.model.dispose()\n yamlModel.model.dispose()\n})\n\nwatch(() => documentSlug, loadDocumentIntoEditor)\n\nwatch(\n () => [path, method] as const,\n async () => {\n await focusOperation()\n },\n)\n\nwatch(isDiagnosticsPaneExpanded, () => {\n syncEditorBottomPadding()\n})\n\nwatch(editorLanguage, async (nextLanguage, previousLanguage) => {\n const wasDirty = isDirty.value\n // Read from the previous model before switching; getEditorValue() would use currentModel\n // which changes with selectedLanguage, so we would read the (empty) new model otherwise.\n const value = getEditorValueForLanguage(previousLanguage ?? 'json')\n if (!value) {\n selectedLanguage.value = nextLanguage\n await nextTick()\n await focusOperation()\n return\n }\n\n const parsed = parseEditorObject(value, previousLanguage ?? 'json')\n selectedLanguage.value = nextLanguage\n await nextTick()\n if (parsed) {\n applyProgrammaticEditorValue(stringifyDocument(parsed, nextLanguage))\n isDirty.value = wasDirty\n }\n await focusOperation()\n})\n\nwatch(\n isAutoSaveEnabled,\n (isEnabled) => {\n if (!isEnabled) {\n debouncedPersist.cleanup()\n return\n }\n\n if (isDirty.value) {\n const value = getEditorValue()\n if (!value) {\n return\n }\n debouncedPersist.execute(EDITOR_PERSIST_DEBOUNCE_KEY, () =>\n persistEditorToWorkspace(value),\n )\n }\n },\n { flush: 'post' },\n)\n</script>\n\n<template>\n <div\n v-if=\"\n collectionType === 'operation' &&\n getOperationContext(path, method) !== null\n \"\n class=\"flex w-full min-w-0 flex-1 flex-col gap-2\"\n :class=\"editorRootClass\">\n <div\n class=\"grid grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-3\">\n <div\n class=\"flex min-w-0 items-center gap-1 overflow-x-auto whitespace-nowrap\">\n <span class=\"text-c-2 text-xs font-medium whitespace-nowrap\">\n Shortcuts\n </span>\n\n <ScalarButton\n class=\"whitespace-nowrap\"\n size=\"xs\"\n variant=\"ghost\"\n @click=\"focusOperation\">\n <span>Operation</span>\n <span class=\"text-c-3 ml-2 text-[11px]\">\n <ScalarHotkey\n hotkey=\"O\"\n :modifier=\"['Alt']\" />\n </span>\n </ScalarButton>\n\n <ScalarButton\n class=\"whitespace-nowrap\"\n size=\"xs\"\n variant=\"ghost\"\n @click=\"focusOperationServers\">\n <span>Servers</span>\n <span class=\"text-c-3 ml-2 text-[11px]\">\n <ScalarHotkey\n hotkey=\"S\"\n :modifier=\"['Alt']\" />\n </span>\n </ScalarButton>\n </div>\n\n <div\n aria-label=\"Editor language\"\n class=\"bg-b-1 shadow-border flex items-center justify-self-center overflow-hidden rounded-lg p-0.5\"\n role=\"tablist\">\n <ScalarButton\n :aria-selected=\"!isYamlMode\"\n :class=\"getLanguageToggleClass(!isYamlMode)\"\n role=\"tab\"\n size=\"xs\"\n type=\"button\"\n variant=\"ghost\"\n @click=\"editorLanguage = 'json'\">\n JSON\n </ScalarButton>\n <ScalarButton\n :aria-selected=\"isYamlMode\"\n :class=\"getLanguageToggleClass(isYamlMode)\"\n role=\"tab\"\n size=\"xs\"\n type=\"button\"\n variant=\"ghost\"\n @click=\"editorLanguage = 'yaml'\">\n YAML\n </ScalarButton>\n </div>\n\n <div class=\"flex min-w-0 shrink-0 items-center gap-2 justify-self-end\">\n <ScalarButton\n size=\"xs\"\n variant=\"ghost\"\n @click=\"formatDocument\">\n <span>Format {{ isYamlMode ? 'YAML' : 'JSON' }}</span>\n <span class=\"text-c-3 ml-2 text-[11px]\">\n <ScalarHotkey\n hotkey=\"F\"\n :modifier=\"['Alt', 'Shift']\" />\n </span>\n </ScalarButton>\n <ScalarButton\n :aria-label=\"\n isEditorMaximized ? 'Restore editor size' : 'Maximize editor'\n \"\n size=\"xs\"\n variant=\"ghost\"\n @click=\"toggleEditorMaximized\">\n <span>{{ isEditorMaximized ? 'Restore' : 'Maximize' }}</span>\n <span class=\"text-c-3 ml-2 text-[11px]\">\n <ScalarIconArrowsIn\n v-if=\"isEditorMaximized\"\n class=\"size-3.5\" />\n <ScalarIconArrowsOut\n v-else\n class=\"size-3.5\" />\n </span>\n </ScalarButton>\n </div>\n </div>\n\n <div class=\"flex min-h-0 w-full min-w-0 flex-1 rounded-lg border\">\n <div\n class=\"relative w-full min-w-0 flex-1\"\n :class=\"isEditorMaximized ? 'h-full min-h-0' : 'h-125'\">\n <div class=\"pointer-events-none absolute top-2 right-2 z-10\">\n <EditorSavePanel\n :isAutoSaveEnabled=\"isAutoSaveEnabled\"\n :isDirty=\"isDirty\"\n :saveLoader=\"saveLoader\"\n @saveNow=\"saveNow\"\n @update:isAutoSaveEnabled=\"isAutoSaveEnabled = $event\" />\n </div>\n\n <EditorDiagnosticsPanel\n :diagnosticCounts=\"diagnosticCounts\"\n :expanded=\"isDiagnosticsPaneExpanded\"\n :visibleDiagnostics=\"visibleDiagnostics\"\n @focusDiagnostic=\"focusDiagnostic\"\n @toggle=\"isDiagnosticsPaneExpanded = !isDiagnosticsPaneExpanded\" />\n\n <div\n ref=\"monacoEditorRef\"\n class=\"h-full w-full min-w-0 flex-1 [&_.monaco-editor]:rounded-lg [&_.overflow-guard]:rounded-lg\" />\n </div>\n </div>\n </div>\n <div v-else>No operation context found</div>\n</template>\n<style scoped>\n.editor-container {\n width: 100%;\n height: 100%;\n}\n\n:deep(.json-path-highlight) {\n background-color: rgba(255, 200, 0, 0.35);\n border-radius: 4px;\n}\n\n:deep(.json-focus-highlight) {\n background-color: color-mix(\n in srgb,\n var(--scalar-color-accent, #24b47e) 18%,\n transparent\n );\n border-radius: 4px;\n}\n</style>\n"],"mappings":"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"}
{"version":3,"file":"Editor.vue.script.js","names":[],"sources":["../../../../../../src/v2/features/collection/components/Editor/Editor.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton, ScalarHotkey, useLoadingState } from '@scalar/components'\nimport { debounce } from '@scalar/helpers/general/debounce'\nimport { isObject } from '@scalar/helpers/object/is-object'\nimport { ScalarIconArrowsIn, ScalarIconArrowsOut } from '@scalar/icons'\nimport * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js'\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n onMounted,\n ref,\n shallowRef,\n watch,\n} from 'vue'\n\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { useEditor, useJsonPointerLinkSupport } from '@/v2/features/editor'\nimport { createJsonModel } from '@/v2/features/editor/helpers/json/create-json-model'\nimport { createYamlModel } from '@/v2/features/editor/helpers/yaml/create-yaml-model'\nimport { useEditorMarkers } from '@/v2/features/editor/hooks/use-editor-markers'\n\nimport EditorDiagnosticsPanel from './components/EditorDiagnosticsPanel.vue'\nimport EditorSavePanel from './components/EditorSavePanel.vue'\nimport { getDiagnosticCounts } from './helpers/get-diagnostic-counts'\nimport { getOperationContext } from './helpers/get-operation-context'\nimport { getVisibleDiagnostics } from './helpers/get-visible-diagnostics'\nimport { parseEditorObject } from './helpers/parse-editor-object'\nimport { stringifyDocument } from './helpers/stringify-document'\nimport { useEditorState } from './hooks/use-editor-state'\n\nconst { collectionType, documentSlug, method, path, workspaceStore } =\n defineProps<CollectionProps>()\n\nconst MAX_VISIBLE_DIAGNOSTICS = 6\nconst EDITOR_PERSIST_DEBOUNCE_KEY = 'editor:replace-document'\n\nconst monacoEditorRef = ref<HTMLElement>()\nconst editorApi = shallowRef<ReturnType<typeof useEditor>>()\n\nconst saveLoader = useLoadingState()\nconst {\n isAutoSaveEnabled,\n isDirty,\n editorLanguage,\n isDiagnosticsPaneExpanded,\n isEditorMaximized,\n isYamlMode,\n editorBottomPadding,\n editorRootClass,\n getLanguageToggleClass,\n toggleEditorMaximized,\n} = useEditorState()\n\nconst jsonModel = createJsonModel()\nconst yamlModel = createYamlModel()\n\nconst selectedLanguage = ref<'json' | 'yaml'>('json')\n\nconst currentModel = computed(() => {\n return selectedLanguage.value === 'json' ? jsonModel : yamlModel\n})\n\nconst monacoEditorInstance = computed(() => editorApi.value?.editor)\nconst { markers: diagnostics } = useEditorMarkers(monacoEditorInstance)\n\nconst syncEditorBottomPadding = () => {\n editorApi.value?.editor.updateOptions({\n padding: {\n top: 0,\n bottom: editorBottomPadding.value,\n },\n })\n}\n\nconst diagnosticCounts = computed(() => getDiagnosticCounts(diagnostics.value))\nconst visibleDiagnostics = computed(() =>\n getVisibleDiagnostics(diagnostics.value, MAX_VISIBLE_DIAGNOSTICS),\n)\n\nconst focusDiagnostic = (marker: monaco.editor.IMarker) => {\n const editor = editorApi.value?.editor\n if (!editor) {\n return\n }\n editor.setSelection({\n startLineNumber: marker.startLineNumber,\n startColumn: marker.startColumn,\n endLineNumber: marker.endLineNumber,\n endColumn: marker.endColumn,\n })\n editor.revealPositionInCenter({\n lineNumber: marker.startLineNumber,\n column: marker.startColumn,\n })\n}\n\nconst getEditorValue = (): string | null => currentModel.value.model.getValue()\n\n/** Value from the editor for a specific language (use when switching to avoid reading the wrong model). */\nconst getEditorValueForLanguage = (language: 'json' | 'yaml'): string | null =>\n (language === 'json' ? jsonModel : yamlModel).model.getValue()\n\nconst getDocumentValue = async (\n language?: 'json' | 'yaml',\n): Promise<string> => {\n const document = await workspaceStore.getEditableDocument(documentSlug)\n return stringifyDocument(document, language ?? selectedLanguage.value)\n}\n\nconst debouncedPersist = debounce({ delay: 1500 })\n\nconst applyProgrammaticEditorValue = (value: string): void => {\n // Cancel pending auto-save work so synthetic model updates do not persist stale data.\n debouncedPersist.cleanup()\n editorApi.value?.setValue(value, true)\n}\n\nconst loadDocumentIntoEditor = async () => {\n applyProgrammaticEditorValue(await getDocumentValue())\n isDirty.value = false\n await focusOperation()\n}\n\nconst formatDocument = async () => {\n await editorApi.value?.formatDocument()\n}\n\nconst focusOperation = async () => {\n const operationContext = getOperationContext(path, method)\n if (!operationContext) {\n return\n }\n\n await editorApi.value?.focusPath([\n 'paths',\n operationContext.path,\n operationContext.method,\n ])\n}\n\nconst persistEditorToWorkspace = async (value: string) => {\n const parsed = parseEditorObject(value, editorLanguage.value)\n if (!parsed) {\n const firstError = diagnostics.value.find(\n (m) => m.severity === monaco.MarkerSeverity.Error,\n )\n if (firstError) {\n focusDiagnostic(firstError)\n }\n await saveLoader.invalidate()\n return\n }\n\n saveLoader.start()\n await workspaceStore.replaceDocument(documentSlug, parsed)\n isDirty.value = false\n await saveLoader.validate({ duration: 900 })\n}\n\nconst saveNow = async () => {\n const value = getEditorValue()\n if (!value) {\n return\n }\n await persistEditorToWorkspace(value)\n}\n\nconst handleEditorChange = (value: string) => {\n isDirty.value = true\n\n if (!isAutoSaveEnabled.value) {\n return\n }\n\n debouncedPersist.execute(EDITOR_PERSIST_DEBOUNCE_KEY, () =>\n persistEditorToWorkspace(value),\n )\n}\n\nconst focusOperationServers = async () => {\n const operationContext = getOperationContext(path, method)\n if (!operationContext) {\n return\n }\n\n const value = getEditorValue()\n if (!value) {\n return\n }\n\n const parsed = parseEditorObject(value, editorLanguage.value)\n\n if (!parsed || !isObject(parsed.paths)) {\n return\n }\n\n const pathsObject = parsed.paths as Record<string, unknown>\n const operationPathItem = pathsObject[operationContext.path]\n if (!isObject(operationPathItem)) {\n return\n }\n\n const operation = operationPathItem[operationContext.method]\n if (!isObject(operation)) {\n return\n }\n\n // Add default servers if not present\n operation.servers ??= []\n\n // Update the editor value\n editorApi.value?.setValue(stringifyDocument(parsed, editorLanguage.value))\n await editorApi.value?.focusPath([\n 'paths',\n operationContext.path,\n operationContext.method,\n 'servers',\n ])\n}\n\nuseJsonPointerLinkSupport(editorApi, currentModel)\n\nonMounted(() => {\n editorApi.value = useEditor({\n element: monacoEditorRef.value ?? document.createElement('div'),\n onChange: handleEditorChange,\n model: currentModel,\n actions: [\n {\n id: 'scalar.editor.focusOperation',\n label: 'Focus Operation',\n keybindings: [monaco.KeyMod.Alt | monaco.KeyCode.KeyO],\n run: async () => {\n await focusOperation()\n },\n },\n {\n id: 'scalar.editor.focusOperationServers',\n label: 'Focus Operation Servers',\n keybindings: [monaco.KeyMod.Alt | monaco.KeyCode.KeyS],\n run: async () => {\n await focusOperationServers()\n },\n },\n {\n id: 'scalar.editor.formatDocument',\n label: 'Format Document',\n keybindings: [\n monaco.KeyMod.Alt | monaco.KeyMod.Shift | monaco.KeyCode.KeyF,\n ],\n run: async () => {\n await formatDocument()\n },\n },\n ],\n })\n\n syncEditorBottomPadding()\n void loadDocumentIntoEditor()\n})\n\nonBeforeUnmount(() => {\n debouncedPersist.cleanup()\n\n // Persist if there is a pending save\n if (isDirty.value && isAutoSaveEnabled.value) {\n void saveNow()\n }\n editorApi.value?.dispose?.()\n // Dispose models created at setup; useEditor only disposes the editor widget, not external models.\n jsonModel.model.dispose()\n yamlModel.model.dispose()\n})\n\nwatch(() => documentSlug, loadDocumentIntoEditor)\n\nwatch(\n () => [path, method] as const,\n async () => {\n await focusOperation()\n },\n)\n\nwatch(isDiagnosticsPaneExpanded, () => {\n syncEditorBottomPadding()\n})\n\nwatch(editorLanguage, async (nextLanguage, previousLanguage) => {\n const wasDirty = isDirty.value\n // Read from the previous model before switching; getEditorValue() would use currentModel\n // which changes with selectedLanguage, so we would read the (empty) new model otherwise.\n const value = getEditorValueForLanguage(previousLanguage ?? 'json')\n if (!value) {\n selectedLanguage.value = nextLanguage\n await nextTick()\n await focusOperation()\n return\n }\n\n const parsed = parseEditorObject(value, previousLanguage ?? 'json')\n selectedLanguage.value = nextLanguage\n await nextTick()\n if (parsed) {\n applyProgrammaticEditorValue(stringifyDocument(parsed, nextLanguage))\n isDirty.value = wasDirty\n }\n await focusOperation()\n})\n\nwatch(\n isAutoSaveEnabled,\n (isEnabled) => {\n if (!isEnabled) {\n debouncedPersist.cleanup()\n return\n }\n\n if (isDirty.value) {\n const value = getEditorValue()\n if (!value) {\n return\n }\n debouncedPersist.execute(EDITOR_PERSIST_DEBOUNCE_KEY, () =>\n persistEditorToWorkspace(value),\n )\n }\n },\n { flush: 'post' },\n)\n</script>\n\n<template>\n <div\n v-if=\"\n collectionType === 'operation' &&\n getOperationContext(path, method) !== null\n \"\n class=\"flex w-full min-w-0 flex-1 flex-col gap-2\"\n :class=\"editorRootClass\">\n <div\n class=\"grid grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-3\">\n <div\n class=\"flex min-w-0 items-center gap-1 overflow-x-auto whitespace-nowrap\">\n <span class=\"text-c-2 text-xs font-medium whitespace-nowrap\">\n Shortcuts\n </span>\n\n <ScalarButton\n class=\"whitespace-nowrap\"\n size=\"xs\"\n variant=\"ghost\"\n @click=\"focusOperation\">\n <span>Operation</span>\n <span class=\"text-c-3 ml-2 text-[11px]\">\n <ScalarHotkey\n hotkey=\"O\"\n :modifier=\"['Alt']\" />\n </span>\n </ScalarButton>\n\n <ScalarButton\n class=\"whitespace-nowrap\"\n size=\"xs\"\n variant=\"ghost\"\n @click=\"focusOperationServers\">\n <span>Servers</span>\n <span class=\"text-c-3 ml-2 text-[11px]\">\n <ScalarHotkey\n hotkey=\"S\"\n :modifier=\"['Alt']\" />\n </span>\n </ScalarButton>\n </div>\n\n <div\n aria-label=\"Editor language\"\n class=\"bg-b-1 shadow-border flex items-center justify-self-center overflow-hidden rounded-lg p-0.5\"\n role=\"tablist\">\n <ScalarButton\n :aria-selected=\"!isYamlMode\"\n :class=\"getLanguageToggleClass(!isYamlMode)\"\n role=\"tab\"\n size=\"xs\"\n type=\"button\"\n variant=\"ghost\"\n @click=\"editorLanguage = 'json'\">\n JSON\n </ScalarButton>\n <ScalarButton\n :aria-selected=\"isYamlMode\"\n :class=\"getLanguageToggleClass(isYamlMode)\"\n role=\"tab\"\n size=\"xs\"\n type=\"button\"\n variant=\"ghost\"\n @click=\"editorLanguage = 'yaml'\">\n YAML\n </ScalarButton>\n </div>\n\n <div class=\"flex min-w-0 shrink-0 items-center gap-2 justify-self-end\">\n <ScalarButton\n size=\"xs\"\n variant=\"ghost\"\n @click=\"formatDocument\">\n <span>Format {{ isYamlMode ? 'YAML' : 'JSON' }}</span>\n <span class=\"text-c-3 ml-2 text-[11px]\">\n <ScalarHotkey\n hotkey=\"F\"\n :modifier=\"['Alt', 'Shift']\" />\n </span>\n </ScalarButton>\n <ScalarButton\n :aria-label=\"\n isEditorMaximized ? 'Restore editor size' : 'Maximize editor'\n \"\n size=\"xs\"\n variant=\"ghost\"\n @click=\"toggleEditorMaximized\">\n <span>{{ isEditorMaximized ? 'Restore' : 'Maximize' }}</span>\n <span class=\"text-c-3 ml-2 text-[11px]\">\n <ScalarIconArrowsIn\n v-if=\"isEditorMaximized\"\n class=\"size-3.5\" />\n <ScalarIconArrowsOut\n v-else\n class=\"size-3.5\" />\n </span>\n </ScalarButton>\n </div>\n </div>\n\n <div class=\"flex min-h-0 w-full min-w-0 flex-1 rounded-lg border\">\n <div\n class=\"relative w-full min-w-0 flex-1\"\n :class=\"isEditorMaximized ? 'h-full min-h-0' : 'h-125'\">\n <div class=\"pointer-events-none absolute top-2 right-2 z-10\">\n <EditorSavePanel\n :isAutoSaveEnabled=\"isAutoSaveEnabled\"\n :isDirty=\"isDirty\"\n :saveLoader=\"saveLoader\"\n @saveNow=\"saveNow\"\n @update:isAutoSaveEnabled=\"isAutoSaveEnabled = $event\" />\n </div>\n\n <EditorDiagnosticsPanel\n :diagnosticCounts=\"diagnosticCounts\"\n :expanded=\"isDiagnosticsPaneExpanded\"\n :visibleDiagnostics=\"visibleDiagnostics\"\n @focusDiagnostic=\"focusDiagnostic\"\n @toggle=\"isDiagnosticsPaneExpanded = !isDiagnosticsPaneExpanded\" />\n\n <div\n ref=\"monacoEditorRef\"\n class=\"h-full w-full min-w-0 flex-1 [&_.monaco-editor]:rounded-lg [&_.overflow-guard]:rounded-lg\" />\n </div>\n </div>\n </div>\n <div v-else>No operation context found</div>\n</template>\n<style scoped>\n.editor-container {\n width: 100%;\n height: 100%;\n}\n\n:deep(.json-path-highlight) {\n background-color: rgba(255, 200, 0, 0.35);\n border-radius: 4px;\n}\n\n:deep(.json-focus-highlight) {\n background-color: color-mix(\n in srgb,\n var(--scalar-color-accent, #24b47e) 18%,\n transparent\n );\n border-radius: 4px;\n}\n</style>\n"],"mappings":"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"}

@@ -24,2 +24,3 @@ import Section_default from "../../settings/components/Section.vue.js";

onUpdateTelemetry: { type: Function },
options: {},
collectionType: {}

@@ -26,0 +27,0 @@ },

@@ -1,1 +0,1 @@

{"version":3,"file":"Environment.vue.script.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Environment.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Environment variables section for the collection.\n * Renders document or workspace environments and lets users set variables\n * that can be referenced in request inputs via {{ variable }}.\n */\nexport default {\n name: 'Environment',\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { EnvironmentsList } from '@/v2/features/environments'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nconst { document, eventBus, collectionType, workspaceStore } =\n defineProps<CollectionProps>()\n\n/** Document or workspace environments */\nconst environments = computed(\n () =>\n (collectionType === 'document'\n ? document['x-scalar-environments']\n : workspaceStore.workspace['x-scalar-environments']) ?? {},\n)\n\nconst activeEnvironment = computed(() => {\n return workspaceStore.workspace['x-scalar-active-environment']\n})\n</script>\n\n<template>\n <Section v-if=\"collectionType !== 'operation'\">\n <template #title>Environment Variables</template>\n <template #description>\n Set environment variables at your collection level. Use\n <code\n v-pre\n class=\"font-code text-c-2\">\n {{ variable }}\n </code>\n to add / search among the selected environment's variables in your request\n inputs.\n </template>\n <EnvironmentsList\n :activeEnvironment\n :collectionType\n :environments\n :eventBus />\n </Section>\n</template>\n"],"mappings":";;;;CAOE,MAAM;;;;;;;;;;;;;;;;;;;;;;;EAeR,MAAM,eAAe,gBAEhB,QAAA,mBAAmB,aAChB,QAAA,SAAS,2BACT,QAAA,eAAe,UAAU,6BAA6B,EAAE,CAChE;EAEA,MAAM,oBAAoB,eAAe;AACvC,UAAO,QAAA,eAAe,UAAU;IACjC;;UAIgB,QAAA,mBAAc,eAAA,WAAA,EAA7B,YAiBU,iBAAA,EAAA,KAAA,GAAA,EAAA;IAhBG,OAAK,cAAsB,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAAA,gBAArB,yBAAqB,GAAA,CAAA,EAAA,CAAA;IAC3B,aAAW,cAEpB,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA;qBAFqB,6DAErB,GAAA;KAAA,mBAIO,QAAA,EAFL,OAAM,sBAAoB,EAAC,oBAE7B,GAAA;qBAAO,wFAGT,GAAA;;2BAKc,CAJd,YAIc,MAAA,yBAAA,EAAA;KAHX,mBAAA,kBAAA;KACA,gBAAA,QAAA;KACA,cAAA,aAAA;KACA,UAAA,QAAA"}
{"version":3,"file":"Environment.vue.script.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Environment.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Environment variables section for the collection.\n * Renders document or workspace environments and lets users set variables\n * that can be referenced in request inputs via {{ variable }}.\n */\nexport default {\n name: 'Environment',\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { EnvironmentsList } from '@/v2/features/environments'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nconst { document, eventBus, collectionType, workspaceStore } =\n defineProps<CollectionProps>()\n\n/** Document or workspace environments */\nconst environments = computed(\n () =>\n (collectionType === 'document'\n ? document['x-scalar-environments']\n : workspaceStore.workspace['x-scalar-environments']) ?? {},\n)\n\nconst activeEnvironment = computed(() => {\n return workspaceStore.workspace['x-scalar-active-environment']\n})\n</script>\n\n<template>\n <Section v-if=\"collectionType !== 'operation'\">\n <template #title>Environment Variables</template>\n <template #description>\n Set environment variables at your collection level. Use\n <code\n v-pre\n class=\"font-code text-c-2\">\n {{ variable }}\n </code>\n to add / search among the selected environment's variables in your request\n inputs.\n </template>\n <EnvironmentsList\n :activeEnvironment\n :collectionType\n :environments\n :eventBus />\n </Section>\n</template>\n"],"mappings":";;;;CAOE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;EAeR,MAAM,eAAe,gBAEhB,QAAA,mBAAmB,aAChB,QAAA,SAAS,2BACT,QAAA,eAAe,UAAU,6BAA6B,EAAE,CAChE;EAEA,MAAM,oBAAoB,eAAe;AACvC,UAAO,QAAA,eAAe,UAAU;IACjC;;UAIgB,QAAA,mBAAc,eAAA,WAAA,EAA7B,YAiBU,iBAAA,EAAA,KAAA,GAAA,EAAA;IAhBG,OAAK,cAAsB,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAAA,gBAArB,yBAAqB,GAAA,CAAA,EAAA,CAAA;IAC3B,aAAW,cAEpB,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA;qBAFqB,6DAErB,GAAA;KAAA,mBAIO,QAAA,EAFL,OAAM,sBAAoB,EAAC,oBAE7B,GAAA;qBAAO,wFAGT,GAAA;;2BAKc,CAJd,YAIc,MAAA,yBAAA,EAAA;KAHX,mBAAA,kBAAA;KACA,gBAAA,QAAA;KACA,cAAA,aAAA;KACA,UAAA,QAAA"}

@@ -13,2 +13,4 @@ import type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments';

environment: XScalarEnvironment;
/** Whether to show context function suggestions like $guid, $timestamp. Defaults to true */
withFakeData?: boolean;
};

@@ -15,0 +17,0 @@ declare var __VLS_9: {};

@@ -1,1 +0,1 @@

{"version":3,"file":"Form.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/collection/components/Form.vue"],"names":[],"mappings":"AA4EA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2EAA2E,CAAA;AAQnH,KAAK,WAAW,GAAG;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,EAAE;QACP,GAAG,EAAE,MAAM,CAAA;QACX,KAAK,EAAE,MAAM,CAAA;QACb,WAAW,EAAE,MAAM,CAAA;QACnB,YAAY,CAAC,EAAE,OAAO,CAAA;KACvB,EAAE,CAAA;IACH,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACzB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAA;IACvD,WAAW,EAAE,kBAAkB,CAAA;CAChC,CAAC;AAyKF,QAAA,IAAI,OAAO,IAAW,CAAE;AACxB,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,CAAC;AAK7C,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"}
{"version":3,"file":"Form.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/collection/components/Form.vue"],"names":[],"mappings":"AA+EA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2EAA2E,CAAA;AAQnH,KAAK,WAAW,GAAG;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,EAAE;QACP,GAAG,EAAE,MAAM,CAAA;QACX,KAAK,EAAE,MAAM,CAAA;QACb,WAAW,EAAE,MAAM,CAAA;QACnB,YAAY,CAAC,EAAE,OAAO,CAAA;KACvB,EAAE,CAAA;IACH,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACzB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAA;IACvD,WAAW,EAAE,kBAAkB,CAAA;IAC/B,4FAA4F;IAC5F,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB,CAAC;AA2KF,QAAA,IAAI,OAAO,IAAW,CAAE;AACxB,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,CAAC;AAK7C,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 +0,1 @@

{"version":3,"file":"Form.vue.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Form.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarIcon } from '@scalar/components'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { useId } from 'vue'\n\nimport ViewLayoutSection from '@/components/ViewLayout/ViewLayoutSection.vue'\nimport DataTable from '@/v2/components/data-table/DataTable.vue'\nimport DataTableInput from '@/v2/components/data-table/DataTableInput.vue'\nimport DataTableRow from '@/v2/components/data-table/DataTableRow.vue'\n\ndefineProps<{\n title?: string\n options: {\n key: string\n label: string\n placeholder: string\n lineWrapping?: boolean\n }[]\n data: Record<string, any>\n onUpdate: (key: string, value: string | number) => void\n environment: XScalarEnvironment\n}>()\n\nconst id = useId()\n</script>\n<template>\n <ViewLayoutSection class=\"last:rounded-b-lg\">\n <template\n v-if=\"title || $slots.title\"\n #title>\n <span v-if=\"title\">{{ title }}</span>\n <slot\n v-else\n name=\"title\" />\n </template>\n <div class=\"flex flex-1 flex-col gap-1.5\">\n <DataTable\n v-if=\"Object.keys(data).length > 0\"\n class=\"rounded-b-lg\"\n :columns=\"['']\">\n <DataTableRow\n v-for=\"(option, index) in options\"\n :key=\"index\">\n <DataTableInput\n :id=\"id\"\n class=\"pr-9\"\n :environment=\"environment\"\n :lineWrapping=\"option.lineWrapping ?? false\"\n :modelValue=\"data[option.key] ?? ''\"\n :placeholder=\"option.placeholder\"\n @update:modelValue=\"onUpdate(option.key, $event)\">\n <template #default>\n <label :for=\"id\">\n {{ option.label }}\n </label>\n </template>\n <template\n v-if=\"option.key === 'description'\"\n #icon>\n <div\n class=\"centered-y bg-b-2 flex-center absolute right-1 z-1 rounded px-1 py-0.5\">\n <ScalarIcon\n icon=\"Markdown\"\n size=\"lg\" />\n </div>\n </template>\n </DataTableInput>\n </DataTableRow>\n </DataTable>\n </div>\n </ViewLayoutSection>\n</template>\n"],"mappings":""}
{"version":3,"file":"Form.vue.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Form.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarIcon } from '@scalar/components'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { useId } from 'vue'\n\nimport ViewLayoutSection from '@/components/ViewLayout/ViewLayoutSection.vue'\nimport DataTable from '@/v2/components/data-table/DataTable.vue'\nimport DataTableInput from '@/v2/components/data-table/DataTableInput.vue'\nimport DataTableRow from '@/v2/components/data-table/DataTableRow.vue'\n\ndefineProps<{\n title?: string\n options: {\n key: string\n label: string\n placeholder: string\n lineWrapping?: boolean\n }[]\n data: Record<string, any>\n onUpdate: (key: string, value: string | number) => void\n environment: XScalarEnvironment\n /** Whether to show context function suggestions like $guid, $timestamp. Defaults to true */\n withFakeData?: boolean\n}>()\n\nconst id = useId()\n</script>\n<template>\n <ViewLayoutSection class=\"last:rounded-b-lg\">\n <template\n v-if=\"title || $slots.title\"\n #title>\n <span v-if=\"title\">{{ title }}</span>\n <slot\n v-else\n name=\"title\" />\n </template>\n <div class=\"flex flex-1 flex-col gap-1.5\">\n <DataTable\n v-if=\"Object.keys(data).length > 0\"\n class=\"rounded-b-lg\"\n :columns=\"['']\">\n <DataTableRow\n v-for=\"(option, index) in options\"\n :key=\"index\">\n <DataTableInput\n :id=\"id\"\n class=\"pr-9\"\n :environment=\"environment\"\n :lineWrapping=\"option.lineWrapping ?? false\"\n :modelValue=\"data[option.key] ?? ''\"\n :placeholder=\"option.placeholder\"\n :withFakeData=\"withFakeData ?? true\"\n @update:modelValue=\"onUpdate(option.key, $event)\">\n <template #default>\n <label :for=\"id\">\n {{ option.label }}\n </label>\n </template>\n <template\n v-if=\"option.key === 'description'\"\n #icon>\n <div\n class=\"centered-y bg-b-2 flex-center absolute right-1 z-1 rounded px-1 py-0.5\">\n <ScalarIcon\n icon=\"Markdown\"\n size=\"lg\" />\n </div>\n </template>\n </DataTableInput>\n </DataTableRow>\n </DataTable>\n </div>\n </ViewLayoutSection>\n</template>\n"],"mappings":""}

@@ -19,3 +19,4 @@ import ViewLayoutSection_default from "../../../../components/ViewLayout/ViewLayoutSection.vue.js";

onUpdate: { type: Function },
environment: {}
environment: {},
withFakeData: { type: Boolean }
},

@@ -40,2 +41,3 @@ setup(__props) {

placeholder: option.placeholder,
withFakeData: __props.withFakeData ?? true,
"onUpdate:modelValue": ($event) => __props.onUpdate(option.key, $event)

@@ -58,2 +60,3 @@ }, createSlots({

"placeholder",
"withFakeData",
"onUpdate:modelValue"

@@ -60,0 +63,0 @@ ])]),

@@ -1,1 +0,1 @@

{"version":3,"file":"Form.vue.script.js","names":["$slots"],"sources":["../../../../../src/v2/features/collection/components/Form.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarIcon } from '@scalar/components'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { useId } from 'vue'\n\nimport ViewLayoutSection from '@/components/ViewLayout/ViewLayoutSection.vue'\nimport DataTable from '@/v2/components/data-table/DataTable.vue'\nimport DataTableInput from '@/v2/components/data-table/DataTableInput.vue'\nimport DataTableRow from '@/v2/components/data-table/DataTableRow.vue'\n\ndefineProps<{\n title?: string\n options: {\n key: string\n label: string\n placeholder: string\n lineWrapping?: boolean\n }[]\n data: Record<string, any>\n onUpdate: (key: string, value: string | number) => void\n environment: XScalarEnvironment\n}>()\n\nconst id = useId()\n</script>\n<template>\n <ViewLayoutSection class=\"last:rounded-b-lg\">\n <template\n v-if=\"title || $slots.title\"\n #title>\n <span v-if=\"title\">{{ title }}</span>\n <slot\n v-else\n name=\"title\" />\n </template>\n <div class=\"flex flex-1 flex-col gap-1.5\">\n <DataTable\n v-if=\"Object.keys(data).length > 0\"\n class=\"rounded-b-lg\"\n :columns=\"['']\">\n <DataTableRow\n v-for=\"(option, index) in options\"\n :key=\"index\">\n <DataTableInput\n :id=\"id\"\n class=\"pr-9\"\n :environment=\"environment\"\n :lineWrapping=\"option.lineWrapping ?? false\"\n :modelValue=\"data[option.key] ?? ''\"\n :placeholder=\"option.placeholder\"\n @update:modelValue=\"onUpdate(option.key, $event)\">\n <template #default>\n <label :for=\"id\">\n {{ option.label }}\n </label>\n </template>\n <template\n v-if=\"option.key === 'description'\"\n #icon>\n <div\n class=\"centered-y bg-b-2 flex-center absolute right-1 z-1 rounded px-1 py-0.5\">\n <ScalarIcon\n icon=\"Markdown\"\n size=\"lg\" />\n </div>\n </template>\n </DataTableInput>\n </DataTableRow>\n </DataTable>\n </div>\n </ViewLayoutSection>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;EAuBA,MAAM,KAAK,OAAM;;uBAGf,YA4CoB,2BAAA,EA5CD,OAAM,qBAAmB,EAAA,YAAA;2BA2CpC,CAlCN,mBAkCM,OAlCN,YAkCM,CAhCI,OAAO,KAAK,QAAA,KAAI,CAAE,SAAM,KAAA,WAAA,EADhC,YAgCY,mBAAA;;KA9BV,OAAM;KACL,SAAS,CAAA,GAAI;;4BAEsB,EAAA,UAAA,KAAA,EADpC,mBA2Be,UAAA,MAAA,WA1Ba,QAAA,UAAlB,QAAQ,UAAK;0BADvB,YA2Be,sBAAA,EAzBZ,KAAK,OAAK,EAAA;8BAwBM,CAvBjB,YAuBiB,wBAAA;QAtBd,IAAI,MAAA,GAAE;QACP,OAAM;QACL,aAAa,QAAA;QACb,cAAc,OAAO,gBAAY;QACjC,YAAY,QAAA,KAAK,OAAO,QAAG;QAC3B,aAAa,OAAO;QACpB,wBAAiB,WAAE,QAAA,SAAS,OAAO,KAAK,OAAM;;QACpC,SAAO,cAGR,CAFR,mBAEQ,SAAA,EAFA,KAAK,MAAA,GAAE,EAAA,EAAA,gBACV,OAAO,MAAK,EAAA,GAAA,WAAA,CAAA,CAAA;;WAIX,OAAO,QAAG,gBAAA;cACf;0BAMK,CALN,mBAKM,OALN,YAKM,CAHJ,YAEc,MAAA,WAAA,EAAA;SADZ,MAAK;SACL,MAAK;;;;;;;;;;;;;;;;;OAnCX,QAAA,SAASA,KAAAA,OAAO,QAAA;UACrB;sBACoC,CAAzB,QAAA,SAAA,WAAA,EAAZ,mBAAqC,QAAA,YAAA,gBAAf,QAAA,MAAK,EAAA,EAAA,IAC3B,WAEiB,KAAA,QAAA,SAAA,EAAA,KAAA,GAAA,CAAA,CAAA,CAAA"}
{"version":3,"file":"Form.vue.script.js","names":["$slots"],"sources":["../../../../../src/v2/features/collection/components/Form.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarIcon } from '@scalar/components'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { useId } from 'vue'\n\nimport ViewLayoutSection from '@/components/ViewLayout/ViewLayoutSection.vue'\nimport DataTable from '@/v2/components/data-table/DataTable.vue'\nimport DataTableInput from '@/v2/components/data-table/DataTableInput.vue'\nimport DataTableRow from '@/v2/components/data-table/DataTableRow.vue'\n\ndefineProps<{\n title?: string\n options: {\n key: string\n label: string\n placeholder: string\n lineWrapping?: boolean\n }[]\n data: Record<string, any>\n onUpdate: (key: string, value: string | number) => void\n environment: XScalarEnvironment\n /** Whether to show context function suggestions like $guid, $timestamp. Defaults to true */\n withFakeData?: boolean\n}>()\n\nconst id = useId()\n</script>\n<template>\n <ViewLayoutSection class=\"last:rounded-b-lg\">\n <template\n v-if=\"title || $slots.title\"\n #title>\n <span v-if=\"title\">{{ title }}</span>\n <slot\n v-else\n name=\"title\" />\n </template>\n <div class=\"flex flex-1 flex-col gap-1.5\">\n <DataTable\n v-if=\"Object.keys(data).length > 0\"\n class=\"rounded-b-lg\"\n :columns=\"['']\">\n <DataTableRow\n v-for=\"(option, index) in options\"\n :key=\"index\">\n <DataTableInput\n :id=\"id\"\n class=\"pr-9\"\n :environment=\"environment\"\n :lineWrapping=\"option.lineWrapping ?? false\"\n :modelValue=\"data[option.key] ?? ''\"\n :placeholder=\"option.placeholder\"\n :withFakeData=\"withFakeData ?? true\"\n @update:modelValue=\"onUpdate(option.key, $event)\">\n <template #default>\n <label :for=\"id\">\n {{ option.label }}\n </label>\n </template>\n <template\n v-if=\"option.key === 'description'\"\n #icon>\n <div\n class=\"centered-y bg-b-2 flex-center absolute right-1 z-1 rounded px-1 py-0.5\">\n <ScalarIcon\n icon=\"Markdown\"\n size=\"lg\" />\n </div>\n </template>\n </DataTableInput>\n </DataTableRow>\n </DataTable>\n </div>\n </ViewLayoutSection>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;EAyBA,MAAM,KAAK,OAAM;;uBAGf,YA6CoB,2BAAA,EA7CD,OAAM,qBAAmB,EAAA,YAAA;2BA4CpC,CAnCN,mBAmCM,OAnCN,YAmCM,CAjCI,OAAO,KAAK,QAAA,KAAI,CAAE,SAAM,KAAA,WAAA,EADhC,YAiCY,mBAAA;;KA/BV,OAAM;KACL,SAAS,CAAA,GAAI;;4BAEsB,EAAA,UAAA,KAAA,EADpC,mBA4Be,UAAA,MAAA,WA3Ba,QAAA,UAAlB,QAAQ,UAAK;0BADvB,YA4Be,sBAAA,EA1BZ,KAAK,OAAK,EAAA;8BAyBM,CAxBjB,YAwBiB,wBAAA;QAvBd,IAAI,MAAA,GAAE;QACP,OAAM;QACL,aAAa,QAAA;QACb,cAAc,OAAO,gBAAY;QACjC,YAAY,QAAA,KAAK,OAAO,QAAG;QAC3B,aAAa,OAAO;QACpB,cAAc,QAAA,gBAAY;QAC1B,wBAAiB,WAAE,QAAA,SAAS,OAAO,KAAK,OAAM;;QACpC,SAAO,cAGR,CAFR,mBAEQ,SAAA,EAFA,KAAK,MAAA,GAAE,EAAA,EAAA,gBACV,OAAO,MAAK,EAAA,GAAA,WAAA,CAAA,CAAA;;WAIX,OAAO,QAAG,gBAAA;cACf;0BAMK,CALN,mBAKM,OALN,YAKM,CAHJ,YAEc,MAAA,WAAA,EAAA;SADZ,MAAK;SACL,MAAK;;;;;;;;;;;;;;;;;;OApCX,QAAA,SAASA,KAAAA,OAAO,QAAA;UACrB;sBACoC,CAAzB,QAAA,SAAA,WAAA,EAAZ,mBAAqC,QAAA,YAAA,gBAAf,QAAA,MAAK,EAAA,EAAA,IAC3B,WAEiB,KAAA,QAAA,SAAA,EAAA,KAAA,GAAA,CAAA,CAAA,CAAA"}

@@ -13,4 +13,4 @@ type __VLS_Props = {

}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
onBlur?: ((value: string) => any) | undefined;
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
onBlur?: ((value: string) => any) | undefined;
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;

@@ -17,0 +17,0 @@ declare const _default: typeof __VLS_export;

@@ -38,2 +38,3 @@ import CodeInput_default from "../../../components/code-input/CodeInput.vue.js";

onUpdateTelemetry: { type: Function },
options: {},
collectionType: {}

@@ -40,0 +41,0 @@ },

@@ -1,1 +0,1 @@

{"version":3,"file":"Overview.vue.script.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Overview.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarMarkdown,\n ScalarModal,\n ScalarToggle,\n useModal,\n} from '@scalar/components'\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport { ScalarIconPencil } from '@scalar/icons'\nimport {\n computed,\n nextTick,\n ref,\n useTemplateRef,\n type ComputedRef,\n type Ref,\n} from 'vue'\n\nimport DeleteSidebarListElement from '@/components/Sidebar/Actions/DeleteSidebarListElement.vue'\nimport { CodeInput } from '@/v2/components/code-input'\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nconst {\n document,\n eventBus,\n layout,\n collectionType,\n path,\n method,\n documentSlug,\n} = defineProps<CollectionProps>()\n\nconst operationLabel = computed(() => {\n if (!method || !path) {\n return 'this operation'\n }\n const upperMethod = typeof method === 'string' ? method.toUpperCase() : method\n return `${upperMethod} ${path}`\n})\n\nconst description: ComputedRef<string> = computed(() => {\n if (collectionType === 'operation') {\n if (!path || !method || !isHttpMethod(method)) {\n return ''\n }\n\n return document?.paths?.[path]?.[method]?.description ?? ''\n }\n\n return document?.info?.description ?? ''\n})\n\nconst deprecated: ComputedRef<boolean> = computed(() => {\n if (collectionType !== 'operation' || !path || !isHttpMethod(method)) {\n return false\n }\n\n const operation = document?.paths?.[path]?.[method] as\n | { deprecated?: boolean }\n | undefined\n return operation?.deprecated ?? false\n})\n\nconst mode: Ref<'edit' | 'preview'> = ref('preview')\n\nconst codeInputRef = useTemplateRef('codeInputRef')\n\n/**\n * Switch between edit and preview modes.\n * When switching to edit mode, focus the input after the DOM updates.\n */\nconst switchMode = async (newMode: 'edit' | 'preview'): Promise<void> => {\n mode.value = newMode\n\n if (newMode === 'edit') {\n await nextTick()\n codeInputRef.value?.focus()\n }\n}\n\n/**\n * Updates the description of the collection\n * @param payload - The new description\n * @returns void\n */\nconst handleDescriptionUpdate = async (payload: string) => {\n await switchMode('preview')\n\n /** If the collection type is a document, update the description of the document */\n if (collectionType === 'document') {\n return eventBus.emit('document:update:info', { description: payload })\n }\n\n /** If the collection type is an operation, update the description of the operation */\n if (collectionType === 'operation') {\n if (!path || !method) {\n console.error('Invalid path or method', { path, method })\n return\n }\n\n return eventBus.emit('operation:update:meta', {\n meta: { path, method },\n payload: {\n description: payload,\n },\n })\n }\n\n console.error('Invalid collection type', { collectionType })\n}\n\nconst handleDeprecatedChange = (value: boolean) => {\n if (collectionType !== 'operation' || !path || !method) {\n return\n }\n\n eventBus.emit('operation:update:meta', {\n meta: { path, method },\n payload: { deprecated: value },\n })\n}\n\nconst deleteOperationModal = useModal()\n\nconst handleDeleteOperation = () => {\n if (collectionType !== 'operation' || !path || !method || !documentSlug) {\n return\n }\n\n eventBus.emit('operation:delete:operation', {\n documentName: documentSlug,\n meta: { path, method },\n })\n deleteOperationModal.hide()\n}\n</script>\n\n<template>\n <div class=\"flex flex-col gap-8\">\n <Section>\n <template #title>Description</template>\n <template #actions>\n <ScalarButton\n v-if=\"mode === 'preview'\"\n class=\"text-c-2 hover:text-c-1 flex items-center gap-2\"\n size=\"sm\"\n type=\"button\"\n variant=\"outlined\"\n @click=\"switchMode('edit')\">\n <ScalarIconPencil\n size=\"sm\"\n thickness=\"1.5\" />\n <span>Edit</span>\n </ScalarButton>\n </template>\n <div class=\"has-focus-visible:bg-b-1 group rounded-lg\">\n <!-- Preview -->\n <template v-if=\"mode === 'preview'\">\n <template v-if=\"description.trim().length\">\n <ScalarMarkdown\n class=\"flex-1 rounded border border-transparent p-1.5 hover:border-(--scalar-background-3)\"\n :value=\"description\"\n withImages\n @dblclick=\"switchMode('edit')\" />\n <div\n class=\"brightness-lifted bg-b-1 absolute inset-0 -z-1 hidden rounded group-hover:block group-has-focus-visible:hidden\" />\n </template>\n\n <div\n v-else\n class=\"text-c-3 flex items-center justify-center rounded-lg border p-4\">\n <ScalarButton\n class=\"hover:bg-b-2 hover:text-c-1 text-c-2 flex items-center gap-2\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"switchMode('edit')\">\n <ScalarIconPencil\n size=\"sm\"\n thickness=\"1.5\" />\n <span>Write a description</span>\n </ScalarButton>\n </div>\n </template>\n\n <!-- Edit -->\n <template v-else>\n <CodeInput\n ref=\"codeInputRef\"\n class=\"border px-0.5 py-0\"\n :environment=\"undefined\"\n :layout=\"layout\"\n :modelValue=\"description\"\n @blur=\"handleDescriptionUpdate\" />\n </template>\n </div>\n </Section>\n\n <!-- Operation-only: Status and Danger Zone -->\n <template v-if=\"collectionType === 'operation'\">\n <Section>\n <template #title>Status</template>\n <div\n class=\"rounded-lg border text-sm transition-colors\"\n :class=\"\n deprecated\n ? 'border-(--scalar-color-alert) bg-(--scalar-background-alert)'\n : 'bg-b-2 border-(--scalar-background-3)'\n \">\n <div class=\"flex items-center justify-between gap-4 rounded-lg p-4\">\n <div class=\"min-w-0 flex-1\">\n <h4\n class=\"font-medium\"\n :class=\"\n deprecated ? 'text-(--scalar-color-alert)' : 'text-c-1'\n \">\n Deprecated\n </h4>\n <p class=\"text-c-2 mt-1.5\">\n Mark this operation as deprecated. Consumers SHOULD refrain from\n using it.\n </p>\n </div>\n <ScalarToggle\n class=\"shrink-0\"\n :modelValue=\"deprecated\"\n @update:modelValue=\"handleDeprecatedChange\" />\n </div>\n </div>\n </Section>\n\n <Section>\n <template #title>Danger Zone</template>\n <div\n class=\"bg-b-2 flex items-center justify-between gap-4 rounded-lg border border-(--scalar-background-3) p-4 text-sm\">\n <div class=\"min-w-0 flex-1\">\n <h4 class=\"text-c-1 font-medium\">Delete Operation</h4>\n <p class=\"text-c-2 mt-1.5\">\n Be careful, my friend. Once deleted, there is no way to recover\n the operation.\n </p>\n </div>\n <ScalarButton\n class=\"shrink-0\"\n size=\"sm\"\n variant=\"danger\"\n @click=\"deleteOperationModal.show()\">\n Delete Operation\n </ScalarButton>\n </div>\n </Section>\n </template>\n </div>\n\n <!-- Delete Operation Modal -->\n <ScalarModal\n :size=\"'xxs'\"\n :state=\"deleteOperationModal\"\n :title=\"`Delete ${operationLabel}`\">\n <DeleteSidebarListElement\n :variableName=\"operationLabel\"\n warningMessage=\"This action cannot be undone.\"\n @close=\"deleteOperationModal.hide()\"\n @delete=\"handleDeleteOperation\" />\n </ScalarModal>\n</template>\n\n<style scoped>\n:deep(.cm-content) {\n min-height: fit-content;\n}\n:deep(.cm-scroller) {\n max-width: 100%;\n overflow-x: auto;\n overflow-y: hidden;\n}\n</style>\n"],"mappings":"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"}
{"version":3,"file":"Overview.vue.script.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Overview.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarMarkdown,\n ScalarModal,\n ScalarToggle,\n useModal,\n} from '@scalar/components'\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport { ScalarIconPencil } from '@scalar/icons'\nimport {\n computed,\n nextTick,\n ref,\n useTemplateRef,\n type ComputedRef,\n type Ref,\n} from 'vue'\n\nimport DeleteSidebarListElement from '@/components/Sidebar/Actions/DeleteSidebarListElement.vue'\nimport { CodeInput } from '@/v2/components/code-input'\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nconst {\n document,\n eventBus,\n layout,\n collectionType,\n path,\n method,\n documentSlug,\n} = defineProps<CollectionProps>()\n\nconst operationLabel = computed(() => {\n if (!method || !path) {\n return 'this operation'\n }\n const upperMethod = typeof method === 'string' ? method.toUpperCase() : method\n return `${upperMethod} ${path}`\n})\n\nconst description: ComputedRef<string> = computed(() => {\n if (collectionType === 'operation') {\n if (!path || !method || !isHttpMethod(method)) {\n return ''\n }\n\n return document?.paths?.[path]?.[method]?.description ?? ''\n }\n\n return document?.info?.description ?? ''\n})\n\nconst deprecated: ComputedRef<boolean> = computed(() => {\n if (collectionType !== 'operation' || !path || !isHttpMethod(method)) {\n return false\n }\n\n const operation = document?.paths?.[path]?.[method] as\n | { deprecated?: boolean }\n | undefined\n return operation?.deprecated ?? false\n})\n\nconst mode: Ref<'edit' | 'preview'> = ref('preview')\n\nconst codeInputRef = useTemplateRef('codeInputRef')\n\n/**\n * Switch between edit and preview modes.\n * When switching to edit mode, focus the input after the DOM updates.\n */\nconst switchMode = async (newMode: 'edit' | 'preview'): Promise<void> => {\n mode.value = newMode\n\n if (newMode === 'edit') {\n await nextTick()\n codeInputRef.value?.focus()\n }\n}\n\n/**\n * Updates the description of the collection\n * @param payload - The new description\n * @returns void\n */\nconst handleDescriptionUpdate = async (payload: string) => {\n await switchMode('preview')\n\n /** If the collection type is a document, update the description of the document */\n if (collectionType === 'document') {\n return eventBus.emit('document:update:info', { description: payload })\n }\n\n /** If the collection type is an operation, update the description of the operation */\n if (collectionType === 'operation') {\n if (!path || !method) {\n console.error('Invalid path or method', { path, method })\n return\n }\n\n return eventBus.emit('operation:update:meta', {\n meta: { path, method },\n payload: {\n description: payload,\n },\n })\n }\n\n console.error('Invalid collection type', { collectionType })\n}\n\nconst handleDeprecatedChange = (value: boolean) => {\n if (collectionType !== 'operation' || !path || !method) {\n return\n }\n\n eventBus.emit('operation:update:meta', {\n meta: { path, method },\n payload: { deprecated: value },\n })\n}\n\nconst deleteOperationModal = useModal()\n\nconst handleDeleteOperation = () => {\n if (collectionType !== 'operation' || !path || !method || !documentSlug) {\n return\n }\n\n eventBus.emit('operation:delete:operation', {\n documentName: documentSlug,\n meta: { path, method },\n })\n deleteOperationModal.hide()\n}\n</script>\n\n<template>\n <div class=\"flex flex-col gap-8\">\n <Section>\n <template #title>Description</template>\n <template #actions>\n <ScalarButton\n v-if=\"mode === 'preview'\"\n class=\"text-c-2 hover:text-c-1 flex items-center gap-2\"\n size=\"sm\"\n type=\"button\"\n variant=\"outlined\"\n @click=\"switchMode('edit')\">\n <ScalarIconPencil\n size=\"sm\"\n thickness=\"1.5\" />\n <span>Edit</span>\n </ScalarButton>\n </template>\n <div class=\"has-focus-visible:bg-b-1 group rounded-lg\">\n <!-- Preview -->\n <template v-if=\"mode === 'preview'\">\n <template v-if=\"description.trim().length\">\n <ScalarMarkdown\n class=\"flex-1 rounded border border-transparent p-1.5 hover:border-(--scalar-background-3)\"\n :value=\"description\"\n withImages\n @dblclick=\"switchMode('edit')\" />\n <div\n class=\"brightness-lifted bg-b-1 absolute inset-0 -z-1 hidden rounded group-hover:block group-has-focus-visible:hidden\" />\n </template>\n\n <div\n v-else\n class=\"text-c-3 flex items-center justify-center rounded-lg border p-4\">\n <ScalarButton\n class=\"hover:bg-b-2 hover:text-c-1 text-c-2 flex items-center gap-2\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"switchMode('edit')\">\n <ScalarIconPencil\n size=\"sm\"\n thickness=\"1.5\" />\n <span>Write a description</span>\n </ScalarButton>\n </div>\n </template>\n\n <!-- Edit -->\n <template v-else>\n <CodeInput\n ref=\"codeInputRef\"\n class=\"border px-0.5 py-0\"\n :environment=\"undefined\"\n :layout=\"layout\"\n :modelValue=\"description\"\n @blur=\"handleDescriptionUpdate\" />\n </template>\n </div>\n </Section>\n\n <!-- Operation-only: Status and Danger Zone -->\n <template v-if=\"collectionType === 'operation'\">\n <Section>\n <template #title>Status</template>\n <div\n class=\"rounded-lg border text-sm transition-colors\"\n :class=\"\n deprecated\n ? 'border-(--scalar-color-alert) bg-(--scalar-background-alert)'\n : 'bg-b-2 border-(--scalar-background-3)'\n \">\n <div class=\"flex items-center justify-between gap-4 rounded-lg p-4\">\n <div class=\"min-w-0 flex-1\">\n <h4\n class=\"font-medium\"\n :class=\"\n deprecated ? 'text-(--scalar-color-alert)' : 'text-c-1'\n \">\n Deprecated\n </h4>\n <p class=\"text-c-2 mt-1.5\">\n Mark this operation as deprecated. Consumers SHOULD refrain from\n using it.\n </p>\n </div>\n <ScalarToggle\n class=\"shrink-0\"\n :modelValue=\"deprecated\"\n @update:modelValue=\"handleDeprecatedChange\" />\n </div>\n </div>\n </Section>\n\n <Section>\n <template #title>Danger Zone</template>\n <div\n class=\"bg-b-2 flex items-center justify-between gap-4 rounded-lg border border-(--scalar-background-3) p-4 text-sm\">\n <div class=\"min-w-0 flex-1\">\n <h4 class=\"text-c-1 font-medium\">Delete Operation</h4>\n <p class=\"text-c-2 mt-1.5\">\n Be careful, my friend. Once deleted, there is no way to recover\n the operation.\n </p>\n </div>\n <ScalarButton\n class=\"shrink-0\"\n size=\"sm\"\n variant=\"danger\"\n @click=\"deleteOperationModal.show()\">\n Delete Operation\n </ScalarButton>\n </div>\n </Section>\n </template>\n </div>\n\n <!-- Delete Operation Modal -->\n <ScalarModal\n :size=\"'xxs'\"\n :state=\"deleteOperationModal\"\n :title=\"`Delete ${operationLabel}`\">\n <DeleteSidebarListElement\n :variableName=\"operationLabel\"\n warningMessage=\"This action cannot be undone.\"\n @close=\"deleteOperationModal.hide()\"\n @delete=\"handleDeleteOperation\" />\n </ScalarModal>\n</template>\n\n<style scoped>\n:deep(.cm-content) {\n min-height: fit-content;\n}\n:deep(.cm-scroller) {\n max-width: 100%;\n overflow-x: auto;\n overflow-y: hidden;\n}\n</style>\n"],"mappings":"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"}

@@ -1,1 +0,1 @@

{"version":3,"file":"Runner.vue.d.ts","sourceRoot":"","sources":["../../../../../../../src/v2/features/collection/components/Runner/components/Runner.vue"],"names":[],"mappings":"AA4xBA,QAAA,MAAM,YAAY;;;;;;;;;;;;kGAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
{"version":3,"file":"Runner.vue.d.ts","sourceRoot":"","sources":["../../../../../../../src/v2/features/collection/components/Runner/components/Runner.vue"],"names":[],"mappings":"AA0yBA,QAAA,MAAM,YAAY;;;;;;;;;;;;kGAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}

@@ -1,1 +0,1 @@

{"version":3,"file":"Runner.vue.js","names":[],"sources":["../../../../../../../src/v2/features/collection/components/Runner/components/Runner.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components'\nimport { ScalarIconArrowCounterClockwise, ScalarIconPlay } from '@scalar/icons'\nimport { computed } from 'vue'\n\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nimport { useRunnerExecution, useRunnerSelection } from '../hooks'\nimport RunnerCard from './RunnerCard.vue'\nimport RunnerOrderItem from './RunnerOrderItem.vue'\nimport RunnerResults from './RunnerResults.vue'\nimport RunnerTree from './RunnerTree.vue'\n\nconst { document, collectionType, workspaceStore, documentSlug, layout } =\n defineProps<CollectionProps>()\n\nconst {\n selectedOrder,\n hasSelection,\n isSelected,\n toggle,\n clearAll,\n removeFromOrder,\n dragState,\n handleDragStart,\n handleDragOver,\n handleDragLeave,\n handleDrop,\n handleDragEnd,\n} = useRunnerSelection({\n isLocked: () => isLocked.value,\n})\n\nconst {\n isRunning,\n hasRunCompleted,\n currentRunIndex,\n runLoader,\n runSummary,\n run,\n rerun,\n clearResults,\n getResultAtIndex,\n isResultPassed,\n isResultSkipped,\n getFailedTests,\n} = useRunnerExecution({\n workspaceStore,\n document,\n documentName: documentSlug,\n isWeb: layout === 'web',\n selectedOrder: computed(() => selectedOrder.value),\n})\n\nconst isLocked = computed(() => isRunning.value || hasRunCompleted.value)\n\nconst { draggedIndex, dragOverIndex, dragOffset } = dragState\n\nconst navigationChildren = computed(() => {\n return document?.['x-scalar-navigation']?.children ?? []\n})\n\nconst hasOperations = computed(() => navigationChildren.value.length > 0)\n</script>\n\n<template>\n <Section v-if=\"collectionType === 'document'\">\n <template #title>Runner</template>\n <template #description>\n Select operation examples, set the run order, then run them in sequence.\n Variables set by pre-request or post-response scripts are shared between\n runs.\n </template>\n\n <div class=\"flex flex-col gap-8 lg:flex-row lg:items-start\">\n <!-- Left: Document operations tree -->\n <RunnerCard\n class=\"min-w-0 flex-1\"\n subtitle=\"Check the examples you want to run. They will be added to the run order.\"\n title=\"Select operations\">\n <div\n v-if=\"hasOperations\"\n class=\"max-h-[28rem] overflow-y-auto\"\n :class=\"{ 'opacity-60': isLocked }\">\n <RunnerTree\n :disabled=\"isLocked\"\n :entries=\"navigationChildren\"\n :isSelected=\"isSelected\"\n :selectedOrder=\"selectedOrder\"\n @toggle=\"toggle\" />\n </div>\n <div\n v-else\n class=\"py-6 text-center\">\n <p class=\"text-c-3 text-sm\">No operations in this document.</p>\n <p class=\"text-c-3 mt-1 text-xs\">\n Add paths and methods to your API description to see them here.\n </p>\n </div>\n </RunnerCard>\n\n <!-- Right: Run order + actions + results -->\n <div class=\"flex w-full shrink-0 flex-col gap-4 lg:w-96\">\n <!-- Run order card -->\n <RunnerCard title=\"Run order\">\n <template #header>\n <ScalarButton\n class=\"transition-opacity duration-100\"\n :class=\"\n hasSelection && !isLocked\n ? 'opacity-100'\n : 'pointer-events-none opacity-0'\n \"\n size=\"xs\"\n variant=\"ghost\"\n @click=\"clearAll\">\n <span class=\"hover:underline\">Clear all</span>\n </ScalarButton>\n </template>\n <template #subtitle>\n {{ selectedOrder.length }}\n {{ selectedOrder.length === 1 ? 'item' : 'items' }} selected.\n <template v-if=\"!isLocked\">Drag to reorder.</template>\n <template v-else-if=\"hasRunCompleted\">\n Clear results to modify.\n </template>\n </template>\n <template #default>\n <div\n v-if=\"selectedOrder.length > 0\"\n class=\"flex flex-col gap-0.5\"\n :class=\"{ 'opacity-60': isLocked }\">\n <RunnerOrderItem\n v-for=\"(item, index) in selectedOrder\"\n :key=\"item.id\"\n :draggable=\"!isLocked\"\n :exampleKey=\"item.exampleKey\"\n :index=\"index\"\n :isDragAfter=\"dragOverIndex === index && dragOffset === 'after'\"\n :isDragBefore=\"\n dragOverIndex === index && dragOffset === 'before'\n \"\n :isDragging=\"draggedIndex === index\"\n :isLocked=\"isLocked\"\n :method=\"item.method\"\n :path=\"item.path\"\n @dragend=\"handleDragEnd\"\n @dragleave=\"handleDragLeave\"\n @dragover=\"handleDragOver(index, $event)\"\n @dragstart=\"handleDragStart(index, $event)\"\n @drop=\"handleDrop\"\n @remove=\"removeFromOrder(item)\" />\n </div>\n <div\n v-else\n class=\"py-4 text-center\">\n <p class=\"text-c-3 text-sm\">No items yet.</p>\n <p class=\"text-c-3 mt-0.5 text-xs\">\n Select operations from the list on the left.\n </p>\n </div>\n </template>\n </RunnerCard>\n\n <!-- Run button -->\n <div class=\"flex justify-end pt-1\">\n <ScalarButton\n v-if=\"!hasRunCompleted\"\n class=\"min-w-40\"\n :disabled=\"!hasSelection || isRunning\"\n :icon=\"ScalarIconPlay\"\n :loader=\"runLoader\"\n size=\"md\"\n variant=\"gradient\"\n @click=\"run\">\n Run sequence\n </ScalarButton>\n <ScalarButton\n v-else\n class=\"min-w-40\"\n :disabled=\"!hasSelection || isRunning\"\n :icon=\"ScalarIconArrowCounterClockwise\"\n :loader=\"runLoader\"\n size=\"md\"\n variant=\"gradient\"\n @click=\"rerun\">\n Re-run sequence\n </ScalarButton>\n </div>\n\n <!-- Running progress -->\n <RunnerCard\n v-if=\"\n isRunning && currentRunIndex != null && selectedOrder.length > 0\n \"\n compact>\n <p class=\"text-c-2 text-sm\">\n Running step\n <span class=\"text-c-1 font-medium\">\n {{ currentRunIndex }} / {{ selectedOrder.length }}\n </span>\n </p>\n <div\n :aria-valuemax=\"selectedOrder.length\"\n :aria-valuemin=\"0\"\n :aria-valuenow=\"currentRunIndex\"\n class=\"bg-b-3 mt-2 h-1.5 overflow-hidden rounded-full\"\n role=\"progressbar\">\n <div\n class=\"bg-accent-color h-full rounded-full transition-[width] duration-200 ease-out\"\n :style=\"{\n width: `${(currentRunIndex / selectedOrder.length) * 100}%`,\n }\" />\n </div>\n </RunnerCard>\n\n <!-- Results -->\n <RunnerResults\n v-if=\"runSummary && hasRunCompleted\"\n :getFailedTests=\"getFailedTests\"\n :getResultAtIndex=\"getResultAtIndex\"\n :isResultPassed=\"isResultPassed\"\n :isResultSkipped=\"isResultSkipped\"\n :selectedOrder=\"selectedOrder\"\n :summary=\"runSummary\"\n @clear=\"clearResults\" />\n </div>\n </div>\n </Section>\n</template>\n"],"mappings":""}
{"version":3,"file":"Runner.vue.js","names":[],"sources":["../../../../../../../src/v2/features/collection/components/Runner/components/Runner.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components'\nimport { ScalarIconArrowCounterClockwise, ScalarIconPlay } from '@scalar/icons'\nimport { computed, toValue } from 'vue'\n\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nimport { useRunnerExecution, useRunnerSelection } from '../hooks'\nimport RunnerCard from './RunnerCard.vue'\nimport RunnerOrderItem from './RunnerOrderItem.vue'\nimport RunnerResults from './RunnerResults.vue'\nimport RunnerTree from './RunnerTree.vue'\n\nconst {\n document,\n collectionType,\n workspaceStore,\n documentSlug,\n layout,\n options,\n} = defineProps<CollectionProps>()\n\nconst {\n selectedOrder,\n hasSelection,\n isSelected,\n toggle,\n clearAll,\n removeFromOrder,\n dragState,\n handleDragStart,\n handleDragOver,\n handleDragLeave,\n handleDrop,\n handleDragEnd,\n} = useRunnerSelection({\n isLocked: () => isLocked.value,\n})\n\nconst {\n isRunning,\n hasRunCompleted,\n currentRunIndex,\n runLoader,\n runSummary,\n run,\n rerun,\n clearResults,\n getResultAtIndex,\n isResultPassed,\n isResultSkipped,\n getFailedTests,\n} = useRunnerExecution({\n workspaceStore,\n document,\n documentName: documentSlug,\n isWeb: layout === 'web',\n selectedOrder: computed(() => selectedOrder.value),\n customFetch: toValue(options)?.customFetch,\n})\n\nconst isLocked = computed(() => isRunning.value || hasRunCompleted.value)\n\nconst { draggedIndex, dragOverIndex, dragOffset } = dragState\n\nconst navigationChildren = computed(() => {\n return document?.['x-scalar-navigation']?.children ?? []\n})\n\nconst hasOperations = computed(() => navigationChildren.value.length > 0)\n</script>\n\n<template>\n <Section v-if=\"collectionType === 'document'\">\n <template #title>Runner</template>\n <template #description>\n Select operation examples, set the run order, then run them in sequence.\n Variables set by pre-request or post-response scripts are shared between\n runs.\n </template>\n\n <div class=\"flex flex-col gap-8 lg:flex-row lg:items-start\">\n <!-- Left: Document operations tree -->\n <RunnerCard\n class=\"min-w-0 flex-1\"\n subtitle=\"Check the examples you want to run. They will be added to the run order.\"\n title=\"Select operations\">\n <div\n v-if=\"hasOperations\"\n class=\"max-h-[28rem] overflow-y-auto\"\n :class=\"{ 'opacity-60': isLocked }\">\n <RunnerTree\n :disabled=\"isLocked\"\n :entries=\"navigationChildren\"\n :isSelected=\"isSelected\"\n :selectedOrder=\"selectedOrder\"\n @toggle=\"toggle\" />\n </div>\n <div\n v-else\n class=\"py-6 text-center\">\n <p class=\"text-c-3 text-sm\">No operations in this document.</p>\n <p class=\"text-c-3 mt-1 text-xs\">\n Add paths and methods to your API description to see them here.\n </p>\n </div>\n </RunnerCard>\n\n <!-- Right: Run order + actions + results -->\n <div class=\"flex w-full shrink-0 flex-col gap-4 lg:w-96\">\n <!-- Run order card -->\n <RunnerCard title=\"Run order\">\n <template #header>\n <ScalarButton\n class=\"transition-opacity duration-100\"\n :class=\"\n hasSelection && !isLocked\n ? 'opacity-100'\n : 'pointer-events-none opacity-0'\n \"\n size=\"xs\"\n variant=\"ghost\"\n @click=\"clearAll\">\n <span class=\"hover:underline\">Clear all</span>\n </ScalarButton>\n </template>\n <template #subtitle>\n {{ selectedOrder.length }}\n {{ selectedOrder.length === 1 ? 'item' : 'items' }} selected.\n <template v-if=\"!isLocked\">Drag to reorder.</template>\n <template v-else-if=\"hasRunCompleted\">\n Clear results to modify.\n </template>\n </template>\n <template #default>\n <div\n v-if=\"selectedOrder.length > 0\"\n class=\"flex flex-col gap-0.5\"\n :class=\"{ 'opacity-60': isLocked }\">\n <RunnerOrderItem\n v-for=\"(item, index) in selectedOrder\"\n :key=\"item.id\"\n :draggable=\"!isLocked\"\n :exampleKey=\"item.exampleKey\"\n :index=\"index\"\n :isDragAfter=\"dragOverIndex === index && dragOffset === 'after'\"\n :isDragBefore=\"\n dragOverIndex === index && dragOffset === 'before'\n \"\n :isDragging=\"draggedIndex === index\"\n :isLocked=\"isLocked\"\n :method=\"item.method\"\n :path=\"item.path\"\n @dragend=\"handleDragEnd\"\n @dragleave=\"handleDragLeave\"\n @dragover=\"handleDragOver(index, $event)\"\n @dragstart=\"handleDragStart(index, $event)\"\n @drop=\"handleDrop\"\n @remove=\"removeFromOrder(item)\" />\n </div>\n <div\n v-else\n class=\"py-4 text-center\">\n <p class=\"text-c-3 text-sm\">No items yet.</p>\n <p class=\"text-c-3 mt-0.5 text-xs\">\n Select operations from the list on the left.\n </p>\n </div>\n </template>\n </RunnerCard>\n\n <!-- Run button -->\n <div class=\"flex justify-end pt-1\">\n <ScalarButton\n v-if=\"!hasRunCompleted\"\n class=\"min-w-40\"\n :disabled=\"!hasSelection || isRunning\"\n :icon=\"ScalarIconPlay\"\n :loader=\"runLoader\"\n size=\"md\"\n variant=\"gradient\"\n @click=\"run\">\n Run sequence\n </ScalarButton>\n <ScalarButton\n v-else\n class=\"min-w-40\"\n :disabled=\"!hasSelection || isRunning\"\n :icon=\"ScalarIconArrowCounterClockwise\"\n :loader=\"runLoader\"\n size=\"md\"\n variant=\"gradient\"\n @click=\"rerun\">\n Re-run sequence\n </ScalarButton>\n </div>\n\n <!-- Running progress -->\n <RunnerCard\n v-if=\"\n isRunning && currentRunIndex != null && selectedOrder.length > 0\n \"\n compact>\n <p class=\"text-c-2 text-sm\">\n Running step\n <span class=\"text-c-1 font-medium\">\n {{ currentRunIndex }} / {{ selectedOrder.length }}\n </span>\n </p>\n <div\n :aria-valuemax=\"selectedOrder.length\"\n :aria-valuemin=\"0\"\n :aria-valuenow=\"currentRunIndex\"\n class=\"bg-b-3 mt-2 h-1.5 overflow-hidden rounded-full\"\n role=\"progressbar\">\n <div\n class=\"bg-accent-color h-full rounded-full transition-[width] duration-200 ease-out\"\n :style=\"{\n width: `${(currentRunIndex / selectedOrder.length) * 100}%`,\n }\" />\n </div>\n </RunnerCard>\n\n <!-- Results -->\n <RunnerResults\n v-if=\"runSummary && hasRunCompleted\"\n :getFailedTests=\"getFailedTests\"\n :getResultAtIndex=\"getResultAtIndex\"\n :isResultPassed=\"isResultPassed\"\n :isResultSkipped=\"isResultSkipped\"\n :selectedOrder=\"selectedOrder\"\n :summary=\"runSummary\"\n @clear=\"clearResults\" />\n </div>\n </div>\n </Section>\n</template>\n"],"mappings":""}

@@ -8,3 +8,3 @@ import Section_default from "../../../../settings/components/Section.vue.js";

import RunnerTree_default from "./RunnerTree.vue.js";
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, normalizeStyle, openBlock, renderList, toDisplayString, unref, withCtx } from "vue";
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, normalizeStyle, openBlock, renderList, toDisplayString, toValue, unref, withCtx } from "vue";
import { ScalarButton } from "@scalar/components";

@@ -47,2 +47,3 @@ import { ScalarIconArrowCounterClockwise, ScalarIconPlay } from "@scalar/icons";

onUpdateTelemetry: { type: Function },
options: {},
collectionType: {}

@@ -57,3 +58,4 @@ },

isWeb: __props.layout === "web",
selectedOrder: computed(() => selectedOrder.value)
selectedOrder: computed(() => selectedOrder.value),
customFetch: toValue(__props.options)?.customFetch
});

@@ -60,0 +62,0 @@ const isLocked = computed(() => isRunning.value || hasRunCompleted.value);

@@ -1,1 +0,1 @@

{"version":3,"file":"Runner.vue.script.js","names":[],"sources":["../../../../../../../src/v2/features/collection/components/Runner/components/Runner.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components'\nimport { ScalarIconArrowCounterClockwise, ScalarIconPlay } from '@scalar/icons'\nimport { computed } from 'vue'\n\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nimport { useRunnerExecution, useRunnerSelection } from '../hooks'\nimport RunnerCard from './RunnerCard.vue'\nimport RunnerOrderItem from './RunnerOrderItem.vue'\nimport RunnerResults from './RunnerResults.vue'\nimport RunnerTree from './RunnerTree.vue'\n\nconst { document, collectionType, workspaceStore, documentSlug, layout } =\n defineProps<CollectionProps>()\n\nconst {\n selectedOrder,\n hasSelection,\n isSelected,\n toggle,\n clearAll,\n removeFromOrder,\n dragState,\n handleDragStart,\n handleDragOver,\n handleDragLeave,\n handleDrop,\n handleDragEnd,\n} = useRunnerSelection({\n isLocked: () => isLocked.value,\n})\n\nconst {\n isRunning,\n hasRunCompleted,\n currentRunIndex,\n runLoader,\n runSummary,\n run,\n rerun,\n clearResults,\n getResultAtIndex,\n isResultPassed,\n isResultSkipped,\n getFailedTests,\n} = useRunnerExecution({\n workspaceStore,\n document,\n documentName: documentSlug,\n isWeb: layout === 'web',\n selectedOrder: computed(() => selectedOrder.value),\n})\n\nconst isLocked = computed(() => isRunning.value || hasRunCompleted.value)\n\nconst { draggedIndex, dragOverIndex, dragOffset } = dragState\n\nconst navigationChildren = computed(() => {\n return document?.['x-scalar-navigation']?.children ?? []\n})\n\nconst hasOperations = computed(() => navigationChildren.value.length > 0)\n</script>\n\n<template>\n <Section v-if=\"collectionType === 'document'\">\n <template #title>Runner</template>\n <template #description>\n Select operation examples, set the run order, then run them in sequence.\n Variables set by pre-request or post-response scripts are shared between\n runs.\n </template>\n\n <div class=\"flex flex-col gap-8 lg:flex-row lg:items-start\">\n <!-- Left: Document operations tree -->\n <RunnerCard\n class=\"min-w-0 flex-1\"\n subtitle=\"Check the examples you want to run. They will be added to the run order.\"\n title=\"Select operations\">\n <div\n v-if=\"hasOperations\"\n class=\"max-h-[28rem] overflow-y-auto\"\n :class=\"{ 'opacity-60': isLocked }\">\n <RunnerTree\n :disabled=\"isLocked\"\n :entries=\"navigationChildren\"\n :isSelected=\"isSelected\"\n :selectedOrder=\"selectedOrder\"\n @toggle=\"toggle\" />\n </div>\n <div\n v-else\n class=\"py-6 text-center\">\n <p class=\"text-c-3 text-sm\">No operations in this document.</p>\n <p class=\"text-c-3 mt-1 text-xs\">\n Add paths and methods to your API description to see them here.\n </p>\n </div>\n </RunnerCard>\n\n <!-- Right: Run order + actions + results -->\n <div class=\"flex w-full shrink-0 flex-col gap-4 lg:w-96\">\n <!-- Run order card -->\n <RunnerCard title=\"Run order\">\n <template #header>\n <ScalarButton\n class=\"transition-opacity duration-100\"\n :class=\"\n hasSelection && !isLocked\n ? 'opacity-100'\n : 'pointer-events-none opacity-0'\n \"\n size=\"xs\"\n variant=\"ghost\"\n @click=\"clearAll\">\n <span class=\"hover:underline\">Clear all</span>\n </ScalarButton>\n </template>\n <template #subtitle>\n {{ selectedOrder.length }}\n {{ selectedOrder.length === 1 ? 'item' : 'items' }} selected.\n <template v-if=\"!isLocked\">Drag to reorder.</template>\n <template v-else-if=\"hasRunCompleted\">\n Clear results to modify.\n </template>\n </template>\n <template #default>\n <div\n v-if=\"selectedOrder.length > 0\"\n class=\"flex flex-col gap-0.5\"\n :class=\"{ 'opacity-60': isLocked }\">\n <RunnerOrderItem\n v-for=\"(item, index) in selectedOrder\"\n :key=\"item.id\"\n :draggable=\"!isLocked\"\n :exampleKey=\"item.exampleKey\"\n :index=\"index\"\n :isDragAfter=\"dragOverIndex === index && dragOffset === 'after'\"\n :isDragBefore=\"\n dragOverIndex === index && dragOffset === 'before'\n \"\n :isDragging=\"draggedIndex === index\"\n :isLocked=\"isLocked\"\n :method=\"item.method\"\n :path=\"item.path\"\n @dragend=\"handleDragEnd\"\n @dragleave=\"handleDragLeave\"\n @dragover=\"handleDragOver(index, $event)\"\n @dragstart=\"handleDragStart(index, $event)\"\n @drop=\"handleDrop\"\n @remove=\"removeFromOrder(item)\" />\n </div>\n <div\n v-else\n class=\"py-4 text-center\">\n <p class=\"text-c-3 text-sm\">No items yet.</p>\n <p class=\"text-c-3 mt-0.5 text-xs\">\n Select operations from the list on the left.\n </p>\n </div>\n </template>\n </RunnerCard>\n\n <!-- Run button -->\n <div class=\"flex justify-end pt-1\">\n <ScalarButton\n v-if=\"!hasRunCompleted\"\n class=\"min-w-40\"\n :disabled=\"!hasSelection || isRunning\"\n :icon=\"ScalarIconPlay\"\n :loader=\"runLoader\"\n size=\"md\"\n variant=\"gradient\"\n @click=\"run\">\n Run sequence\n </ScalarButton>\n <ScalarButton\n v-else\n class=\"min-w-40\"\n :disabled=\"!hasSelection || isRunning\"\n :icon=\"ScalarIconArrowCounterClockwise\"\n :loader=\"runLoader\"\n size=\"md\"\n variant=\"gradient\"\n @click=\"rerun\">\n Re-run sequence\n </ScalarButton>\n </div>\n\n <!-- Running progress -->\n <RunnerCard\n v-if=\"\n isRunning && currentRunIndex != null && selectedOrder.length > 0\n \"\n compact>\n <p class=\"text-c-2 text-sm\">\n Running step\n <span class=\"text-c-1 font-medium\">\n {{ currentRunIndex }} / {{ selectedOrder.length }}\n </span>\n </p>\n <div\n :aria-valuemax=\"selectedOrder.length\"\n :aria-valuemin=\"0\"\n :aria-valuenow=\"currentRunIndex\"\n class=\"bg-b-3 mt-2 h-1.5 overflow-hidden rounded-full\"\n role=\"progressbar\">\n <div\n class=\"bg-accent-color h-full rounded-full transition-[width] duration-200 ease-out\"\n :style=\"{\n width: `${(currentRunIndex / selectedOrder.length) * 100}%`,\n }\" />\n </div>\n </RunnerCard>\n\n <!-- Results -->\n <RunnerResults\n v-if=\"runSummary && hasRunCompleted\"\n :getFailedTests=\"getFailedTests\"\n :getResultAtIndex=\"getResultAtIndex\"\n :isResultPassed=\"isResultPassed\"\n :isResultSkipped=\"isResultSkipped\"\n :selectedOrder=\"selectedOrder\"\n :summary=\"runSummary\"\n @clear=\"clearResults\" />\n </div>\n </div>\n </Section>\n</template>\n"],"mappings":"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"}
{"version":3,"file":"Runner.vue.script.js","names":[],"sources":["../../../../../../../src/v2/features/collection/components/Runner/components/Runner.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components'\nimport { ScalarIconArrowCounterClockwise, ScalarIconPlay } from '@scalar/icons'\nimport { computed, toValue } from 'vue'\n\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nimport { useRunnerExecution, useRunnerSelection } from '../hooks'\nimport RunnerCard from './RunnerCard.vue'\nimport RunnerOrderItem from './RunnerOrderItem.vue'\nimport RunnerResults from './RunnerResults.vue'\nimport RunnerTree from './RunnerTree.vue'\n\nconst {\n document,\n collectionType,\n workspaceStore,\n documentSlug,\n layout,\n options,\n} = defineProps<CollectionProps>()\n\nconst {\n selectedOrder,\n hasSelection,\n isSelected,\n toggle,\n clearAll,\n removeFromOrder,\n dragState,\n handleDragStart,\n handleDragOver,\n handleDragLeave,\n handleDrop,\n handleDragEnd,\n} = useRunnerSelection({\n isLocked: () => isLocked.value,\n})\n\nconst {\n isRunning,\n hasRunCompleted,\n currentRunIndex,\n runLoader,\n runSummary,\n run,\n rerun,\n clearResults,\n getResultAtIndex,\n isResultPassed,\n isResultSkipped,\n getFailedTests,\n} = useRunnerExecution({\n workspaceStore,\n document,\n documentName: documentSlug,\n isWeb: layout === 'web',\n selectedOrder: computed(() => selectedOrder.value),\n customFetch: toValue(options)?.customFetch,\n})\n\nconst isLocked = computed(() => isRunning.value || hasRunCompleted.value)\n\nconst { draggedIndex, dragOverIndex, dragOffset } = dragState\n\nconst navigationChildren = computed(() => {\n return document?.['x-scalar-navigation']?.children ?? []\n})\n\nconst hasOperations = computed(() => navigationChildren.value.length > 0)\n</script>\n\n<template>\n <Section v-if=\"collectionType === 'document'\">\n <template #title>Runner</template>\n <template #description>\n Select operation examples, set the run order, then run them in sequence.\n Variables set by pre-request or post-response scripts are shared between\n runs.\n </template>\n\n <div class=\"flex flex-col gap-8 lg:flex-row lg:items-start\">\n <!-- Left: Document operations tree -->\n <RunnerCard\n class=\"min-w-0 flex-1\"\n subtitle=\"Check the examples you want to run. They will be added to the run order.\"\n title=\"Select operations\">\n <div\n v-if=\"hasOperations\"\n class=\"max-h-[28rem] overflow-y-auto\"\n :class=\"{ 'opacity-60': isLocked }\">\n <RunnerTree\n :disabled=\"isLocked\"\n :entries=\"navigationChildren\"\n :isSelected=\"isSelected\"\n :selectedOrder=\"selectedOrder\"\n @toggle=\"toggle\" />\n </div>\n <div\n v-else\n class=\"py-6 text-center\">\n <p class=\"text-c-3 text-sm\">No operations in this document.</p>\n <p class=\"text-c-3 mt-1 text-xs\">\n Add paths and methods to your API description to see them here.\n </p>\n </div>\n </RunnerCard>\n\n <!-- Right: Run order + actions + results -->\n <div class=\"flex w-full shrink-0 flex-col gap-4 lg:w-96\">\n <!-- Run order card -->\n <RunnerCard title=\"Run order\">\n <template #header>\n <ScalarButton\n class=\"transition-opacity duration-100\"\n :class=\"\n hasSelection && !isLocked\n ? 'opacity-100'\n : 'pointer-events-none opacity-0'\n \"\n size=\"xs\"\n variant=\"ghost\"\n @click=\"clearAll\">\n <span class=\"hover:underline\">Clear all</span>\n </ScalarButton>\n </template>\n <template #subtitle>\n {{ selectedOrder.length }}\n {{ selectedOrder.length === 1 ? 'item' : 'items' }} selected.\n <template v-if=\"!isLocked\">Drag to reorder.</template>\n <template v-else-if=\"hasRunCompleted\">\n Clear results to modify.\n </template>\n </template>\n <template #default>\n <div\n v-if=\"selectedOrder.length > 0\"\n class=\"flex flex-col gap-0.5\"\n :class=\"{ 'opacity-60': isLocked }\">\n <RunnerOrderItem\n v-for=\"(item, index) in selectedOrder\"\n :key=\"item.id\"\n :draggable=\"!isLocked\"\n :exampleKey=\"item.exampleKey\"\n :index=\"index\"\n :isDragAfter=\"dragOverIndex === index && dragOffset === 'after'\"\n :isDragBefore=\"\n dragOverIndex === index && dragOffset === 'before'\n \"\n :isDragging=\"draggedIndex === index\"\n :isLocked=\"isLocked\"\n :method=\"item.method\"\n :path=\"item.path\"\n @dragend=\"handleDragEnd\"\n @dragleave=\"handleDragLeave\"\n @dragover=\"handleDragOver(index, $event)\"\n @dragstart=\"handleDragStart(index, $event)\"\n @drop=\"handleDrop\"\n @remove=\"removeFromOrder(item)\" />\n </div>\n <div\n v-else\n class=\"py-4 text-center\">\n <p class=\"text-c-3 text-sm\">No items yet.</p>\n <p class=\"text-c-3 mt-0.5 text-xs\">\n Select operations from the list on the left.\n </p>\n </div>\n </template>\n </RunnerCard>\n\n <!-- Run button -->\n <div class=\"flex justify-end pt-1\">\n <ScalarButton\n v-if=\"!hasRunCompleted\"\n class=\"min-w-40\"\n :disabled=\"!hasSelection || isRunning\"\n :icon=\"ScalarIconPlay\"\n :loader=\"runLoader\"\n size=\"md\"\n variant=\"gradient\"\n @click=\"run\">\n Run sequence\n </ScalarButton>\n <ScalarButton\n v-else\n class=\"min-w-40\"\n :disabled=\"!hasSelection || isRunning\"\n :icon=\"ScalarIconArrowCounterClockwise\"\n :loader=\"runLoader\"\n size=\"md\"\n variant=\"gradient\"\n @click=\"rerun\">\n Re-run sequence\n </ScalarButton>\n </div>\n\n <!-- Running progress -->\n <RunnerCard\n v-if=\"\n isRunning && currentRunIndex != null && selectedOrder.length > 0\n \"\n compact>\n <p class=\"text-c-2 text-sm\">\n Running step\n <span class=\"text-c-1 font-medium\">\n {{ currentRunIndex }} / {{ selectedOrder.length }}\n </span>\n </p>\n <div\n :aria-valuemax=\"selectedOrder.length\"\n :aria-valuemin=\"0\"\n :aria-valuenow=\"currentRunIndex\"\n class=\"bg-b-3 mt-2 h-1.5 overflow-hidden rounded-full\"\n role=\"progressbar\">\n <div\n class=\"bg-accent-color h-full rounded-full transition-[width] duration-200 ease-out\"\n :style=\"{\n width: `${(currentRunIndex / selectedOrder.length) * 100}%`,\n }\" />\n </div>\n </RunnerCard>\n\n <!-- Results -->\n <RunnerResults\n v-if=\"runSummary && hasRunCompleted\"\n :getFailedTests=\"getFailedTests\"\n :getResultAtIndex=\"getResultAtIndex\"\n :isResultPassed=\"isResultPassed\"\n :isResultSkipped=\"isResultSkipped\"\n :selectedOrder=\"selectedOrder\"\n :summary=\"runSummary\"\n @clear=\"clearResults\" />\n </div>\n </div>\n </Section>\n</template>\n"],"mappings":"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"}

@@ -12,5 +12,5 @@ import type { HttpMethod } from '@scalar/helpers/http/http-methods';

declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
toggle: (path: string, method: "delete" | "head" | "get" | "options" | "put" | "post" | "patch" | "trace", exampleKey: string, label: string) => any;
toggle: (path: string, method: "head" | "delete" | "get" | "options" | "patch" | "post" | "put" | "trace", exampleKey: string, label: string) => any;
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
onToggle?: ((path: string, method: "delete" | "head" | "get" | "options" | "put" | "post" | "patch" | "trace", exampleKey: string, label: string) => any) | undefined;
onToggle?: ((path: string, method: "head" | "delete" | "get" | "options" | "patch" | "post" | "put" | "trace", exampleKey: string, label: string) => any) | undefined;
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;

@@ -17,0 +17,0 @@ declare const _default: typeof __VLS_export;

@@ -5,3 +5,3 @@ import { useLoadingState } from '@scalar/components';

import { type ComputedRef, type Ref } from 'vue';
import { type ResponseInstance } from '../../../../../../v2/blocks/operation-block/helpers/send-request.js';
import { type CustomFetch, type ResponseInstance } from '../../../../../../v2/blocks/operation-block/helpers/send-request.js';
import type { SelectedItem } from './use-runner-selection.js';

@@ -40,2 +40,4 @@ export type TestResult = {

selectedOrder: ComputedRef<SelectedItem[]>;
/** Optional custom fetch implementation, overrides the global fetch for request execution */
customFetch?: CustomFetch;
};

@@ -73,4 +75,4 @@ type UseRunnerExecutionReturn = {

*/
export declare function useRunnerExecution({ workspaceStore, document, documentName, isWeb, selectedOrder, }: UseRunnerExecutionOptions): UseRunnerExecutionReturn;
export declare function useRunnerExecution({ workspaceStore, document, documentName, isWeb, selectedOrder, customFetch, }: UseRunnerExecutionOptions): UseRunnerExecutionReturn;
export {};
//# sourceMappingURL=use-runner-execution.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"use-runner-execution.d.ts","sourceRoot":"","sources":["../../../../../../../src/v2/features/collection/components/Runner/hooks/use-runner-execution.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"use-runner-execution.d.ts","sourceRoot":"","sources":["../../../../../../../src/v2/features/collection/components/Runner/hooks/use-runner-execution.ts"],"names":[],"mappings":"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"}

@@ -13,3 +13,3 @@ import { sendRequest } from "../../../../../blocks/operation-block/helpers/send-request.js";

*/
function useRunnerExecution({ workspaceStore, document, documentName, isWeb, selectedOrder }) {
function useRunnerExecution({ workspaceStore, document, documentName, isWeb, selectedOrder, customFetch }) {
const isRunning = ref(false);

@@ -140,3 +140,4 @@ const hasRunCompleted = ref(false);

isUsingProxy: requestResult.data.isUsingProxy,
requestPayload: requestResult.data.requestPayload
requestPayload: requestResult.data.requestPayload,
customFetch
});

@@ -143,0 +144,0 @@ if (sendError) {

@@ -1,1 +0,1 @@

{"version":3,"file":"use-runner-execution.js","names":[],"sources":["../../../../../../../src/v2/features/collection/components/Runner/hooks/use-runner-execution.ts"],"sourcesContent":["import { useLoadingState } from '@scalar/components'\nimport { isElectron } from '@scalar/helpers/general/is-electron'\nimport { executePostResponseScript, executePreRequestScript, getScript } from '@scalar/pre-post-request-scripts'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport {\n type BuildRequestExampleContext,\n buildRequest,\n createVariablesStoreForRequest,\n getEnvironmentVariables,\n getRequestExampleContext,\n requestFactory,\n} from '@scalar/workspace-store/request-example'\nimport type { OpenApiDocument } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { type ComputedRef, type Ref, computed, ref } from 'vue'\n\nimport { type ResponseInstance, sendRequest } from '@/v2/blocks/operation-block/helpers/send-request'\nimport { APP_VERSION } from '@/v2/constants'\nimport { tryCatch } from '@/v2/helpers/safe-run'\n\nimport type { SelectedItem } from './use-runner-selection'\n\nexport type TestResult = {\n title: string\n passed: boolean\n duration: number\n error?: string\n status: 'pending' | 'passed' | 'failed'\n}\n\nexport type RunResult = {\n item: SelectedItem\n result: ResponseInstance | null\n error: Error | null\n testResults: TestResult[]\n}\n\nexport type RunSummary = {\n total: number\n passed: number\n failed: number\n skipped: number\n duration: number | null\n allPassed: boolean\n}\n\ntype UseRunnerExecutionOptions = {\n /** Workspace store */\n workspaceStore: WorkspaceStore\n /** Document */\n document: OpenApiDocument | null\n /** Document name */\n documentName: string\n /** Whether the layout is web */\n isWeb: boolean\n /** Ordered list of selected items to run */\n selectedOrder: ComputedRef<SelectedItem[]>\n}\n\ntype UseRunnerExecutionReturn = {\n /** Whether a run is currently in progress */\n isRunning: Ref<boolean>\n /** Whether a run has completed */\n hasRunCompleted: Ref<boolean>\n /** Current index being run (1-based) */\n currentRunIndex: Ref<number | null>\n /** Loading state for the run button */\n runLoader: ReturnType<typeof useLoadingState>\n /** Results from the run */\n runResults: Ref<RunResult[]>\n /** Summary of the run results */\n runSummary: ComputedRef<RunSummary | null>\n /** Start running the selected items */\n run: () => Promise<void>\n /** Clear results and run again */\n rerun: () => void\n /** Clear all results */\n clearResults: () => void\n /** Get the result at a specific index */\n getResultAtIndex: (index: number) => RunResult | null\n /** Check if a result passed */\n isResultPassed: (result: RunResult | null) => boolean\n /** Check if a result was skipped */\n isResultSkipped: (index: number) => boolean\n /** Get failed tests from a result */\n getFailedTests: (result: RunResult | null) => TestResult[]\n}\n\n/**\n * Composable for managing runner execution state and logic.\n */\nexport function useRunnerExecution({\n workspaceStore,\n document,\n documentName,\n isWeb,\n selectedOrder,\n}: UseRunnerExecutionOptions): UseRunnerExecutionReturn {\n const isRunning = ref(false)\n const hasRunCompleted = ref(false)\n const currentRunIndex = ref<number | null>(null)\n const runLoader = useLoadingState()\n const runResults = ref<RunResult[]>([])\n const runStartTime = ref<number | null>(null)\n const runEndTime = ref<number | null>(null)\n\n const runSummary = computed<RunSummary | null>(() => {\n if (runResults.value.length === 0 && !hasRunCompleted.value) {\n return null\n }\n const ran = runResults.value.length\n const total = selectedOrder.value.length\n const passed = runResults.value.filter((r) => !r.error && r.testResults.every((t) => t.passed)).length\n const failed = ran - passed\n const skipped = total - ran\n const duration = runStartTime.value && runEndTime.value ? runEndTime.value - runStartTime.value : null\n const allPassed = failed === 0 && skipped === 0\n return { total, passed, failed, skipped, duration, allPassed }\n })\n\n const clearResults = () => {\n runResults.value = []\n hasRunCompleted.value = false\n runStartTime.value = null\n runEndTime.value = null\n }\n\n const rerun = () => {\n clearResults()\n void run()\n }\n\n const getResultAtIndex = (index: number): RunResult | null => {\n return runResults.value[index] ?? null\n }\n\n const isResultPassed = (result: RunResult | null): boolean => {\n if (!result) {\n return false\n }\n if (result.error) {\n return false\n }\n if (result.testResults.some((t) => !t.passed)) {\n return false\n }\n return true\n }\n\n const isResultSkipped = (index: number): boolean => {\n return hasRunCompleted.value && getResultAtIndex(index) === null\n }\n\n const getFailedTests = (result: RunResult | null): TestResult[] => {\n if (!result) {\n return []\n }\n return result.testResults.filter((t) => !t.passed)\n }\n\n const getContext = (item: SelectedItem) => {\n const contextResult = getRequestExampleContext(\n workspaceStore,\n documentName,\n { path: item.path, method: item.method, exampleName: item.exampleKey },\n {\n fallbackDocument: document,\n isElectron: isElectron(),\n layout: isWeb ? 'web' : 'other',\n appVersion: APP_VERSION,\n },\n )\n\n return contextResult\n }\n\n const getRequestFactory = (ctx: BuildRequestExampleContext, item: SelectedItem) => {\n const globalCookies = [...ctx.cookies.workspace, ...ctx.cookies.document]\n return requestFactory({\n defaultHeaders: ctx.headers.default,\n environment: ctx.environment.environment,\n exampleName: item.exampleKey,\n globalCookies,\n method: item.method,\n operation: ctx.operation,\n path: item.path,\n proxyUrl: ctx.proxy.url ?? '',\n server: ctx.servers.selected,\n selectedSecuritySchemes: ctx.security.selectedSchemes,\n isElectron: isElectron(),\n })\n }\n\n const run = async () => {\n if (isRunning.value || !document || selectedOrder.value.length === 0) {\n return\n }\n\n isRunning.value = true\n hasRunCompleted.value = false\n runLoader.start()\n runResults.value = []\n currentRunIndex.value = 0\n runStartTime.value = performance.now()\n runEndTime.value = null\n\n const variablesStore = createVariablesStoreForRequest()\n\n // Run each item in the selected order\n for (let i = 0; i < selectedOrder.value.length; i++) {\n currentRunIndex.value = i + 1\n const item = selectedOrder.value[i]!\n\n // Create a run result for the current item\n const runResult: RunResult = {\n item,\n result: null,\n error: null,\n testResults: [],\n }\n\n try {\n const contextResult = getContext(item)\n\n if (!contextResult.ok) {\n runResult.error = new Error(contextResult.error)\n runResults.value = [...runResults.value, runResult]\n continue\n }\n\n const { request: requestBuilder } = getRequestFactory(contextResult.data, item)\n\n const preRequestScript = getScript(document['x-pre-request'], contextResult.data.operation['x-pre-request'])\n await executePreRequestScript(preRequestScript, {\n requestBuilder,\n variablesStore,\n onTestResultsUpdate: (newResults) => {\n runResult.testResults = [...newResults]\n },\n })\n\n const envVariables = {\n ...getEnvironmentVariables(contextResult.data.environment.environment),\n ...variablesStore.getVariables(),\n }\n\n const requestResult = await tryCatch(() => {\n return buildRequest(requestBuilder, { envVariables })\n })\n\n if (!requestResult.ok) {\n runResult.error = new Error(requestResult.error)\n runResults.value = [...runResults.value, runResult]\n continue\n }\n\n const [sendError, sendResult] = await sendRequest({\n isUsingProxy: requestResult.data.isUsingProxy,\n requestPayload: requestResult.data.requestPayload,\n })\n\n if (sendError) {\n runResult.error = sendError\n runResults.value = [...runResults.value, runResult]\n continue\n }\n\n runResult.result = sendResult.response\n\n const postResponseScript = getScript(\n document['x-post-response'],\n contextResult.data.operation['x-post-response'],\n )\n\n const preRequestResults = [...runResult.testResults]\n await executePostResponseScript(postResponseScript, {\n requestBuilder,\n response: sendResult.originalResponse.clone(),\n variablesStore,\n onTestResultsUpdate: (postResponseResults) => {\n runResult.testResults = [...preRequestResults, ...postResponseResults]\n },\n })\n\n runResults.value = [...runResults.value, runResult]\n\n const hasTestFailure = runResult.testResults.some((t) => !t.passed)\n if (hasTestFailure) {\n break\n }\n } catch (error) {\n runResult.error = error instanceof Error ? error : new Error(String(error))\n runResults.value = [...runResults.value, runResult]\n break\n }\n }\n\n isRunning.value = false\n hasRunCompleted.value = true\n runEndTime.value = performance.now()\n void runLoader.clear()\n currentRunIndex.value = null\n }\n\n return {\n isRunning,\n hasRunCompleted,\n currentRunIndex,\n runLoader,\n runResults,\n runSummary,\n run,\n rerun,\n clearResults,\n getResultAtIndex,\n isResultPassed,\n isResultSkipped,\n getFailedTests,\n }\n}\n"],"mappings":"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"}
{"version":3,"file":"use-runner-execution.js","names":[],"sources":["../../../../../../../src/v2/features/collection/components/Runner/hooks/use-runner-execution.ts"],"sourcesContent":["import { useLoadingState } from '@scalar/components'\nimport { isElectron } from '@scalar/helpers/general/is-electron'\nimport { executePostResponseScript, executePreRequestScript, getScript } from '@scalar/pre-post-request-scripts'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport {\n type BuildRequestExampleContext,\n buildRequest,\n createVariablesStoreForRequest,\n getEnvironmentVariables,\n getRequestExampleContext,\n requestFactory,\n} from '@scalar/workspace-store/request-example'\nimport type { OpenApiDocument } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { type ComputedRef, type Ref, computed, ref } from 'vue'\n\nimport { type CustomFetch, type ResponseInstance, sendRequest } from '@/v2/blocks/operation-block/helpers/send-request'\nimport { APP_VERSION } from '@/v2/constants'\nimport { tryCatch } from '@/v2/helpers/safe-run'\n\nimport type { SelectedItem } from './use-runner-selection'\n\nexport type TestResult = {\n title: string\n passed: boolean\n duration: number\n error?: string\n status: 'pending' | 'passed' | 'failed'\n}\n\nexport type RunResult = {\n item: SelectedItem\n result: ResponseInstance | null\n error: Error | null\n testResults: TestResult[]\n}\n\nexport type RunSummary = {\n total: number\n passed: number\n failed: number\n skipped: number\n duration: number | null\n allPassed: boolean\n}\n\ntype UseRunnerExecutionOptions = {\n /** Workspace store */\n workspaceStore: WorkspaceStore\n /** Document */\n document: OpenApiDocument | null\n /** Document name */\n documentName: string\n /** Whether the layout is web */\n isWeb: boolean\n /** Ordered list of selected items to run */\n selectedOrder: ComputedRef<SelectedItem[]>\n /** Optional custom fetch implementation, overrides the global fetch for request execution */\n customFetch?: CustomFetch\n}\n\ntype UseRunnerExecutionReturn = {\n /** Whether a run is currently in progress */\n isRunning: Ref<boolean>\n /** Whether a run has completed */\n hasRunCompleted: Ref<boolean>\n /** Current index being run (1-based) */\n currentRunIndex: Ref<number | null>\n /** Loading state for the run button */\n runLoader: ReturnType<typeof useLoadingState>\n /** Results from the run */\n runResults: Ref<RunResult[]>\n /** Summary of the run results */\n runSummary: ComputedRef<RunSummary | null>\n /** Start running the selected items */\n run: () => Promise<void>\n /** Clear results and run again */\n rerun: () => void\n /** Clear all results */\n clearResults: () => void\n /** Get the result at a specific index */\n getResultAtIndex: (index: number) => RunResult | null\n /** Check if a result passed */\n isResultPassed: (result: RunResult | null) => boolean\n /** Check if a result was skipped */\n isResultSkipped: (index: number) => boolean\n /** Get failed tests from a result */\n getFailedTests: (result: RunResult | null) => TestResult[]\n}\n\n/**\n * Composable for managing runner execution state and logic.\n */\nexport function useRunnerExecution({\n workspaceStore,\n document,\n documentName,\n isWeb,\n selectedOrder,\n customFetch,\n}: UseRunnerExecutionOptions): UseRunnerExecutionReturn {\n const isRunning = ref(false)\n const hasRunCompleted = ref(false)\n const currentRunIndex = ref<number | null>(null)\n const runLoader = useLoadingState()\n const runResults = ref<RunResult[]>([])\n const runStartTime = ref<number | null>(null)\n const runEndTime = ref<number | null>(null)\n\n const runSummary = computed<RunSummary | null>(() => {\n if (runResults.value.length === 0 && !hasRunCompleted.value) {\n return null\n }\n const ran = runResults.value.length\n const total = selectedOrder.value.length\n const passed = runResults.value.filter((r) => !r.error && r.testResults.every((t) => t.passed)).length\n const failed = ran - passed\n const skipped = total - ran\n const duration = runStartTime.value && runEndTime.value ? runEndTime.value - runStartTime.value : null\n const allPassed = failed === 0 && skipped === 0\n return { total, passed, failed, skipped, duration, allPassed }\n })\n\n const clearResults = () => {\n runResults.value = []\n hasRunCompleted.value = false\n runStartTime.value = null\n runEndTime.value = null\n }\n\n const rerun = () => {\n clearResults()\n void run()\n }\n\n const getResultAtIndex = (index: number): RunResult | null => {\n return runResults.value[index] ?? null\n }\n\n const isResultPassed = (result: RunResult | null): boolean => {\n if (!result) {\n return false\n }\n if (result.error) {\n return false\n }\n if (result.testResults.some((t) => !t.passed)) {\n return false\n }\n return true\n }\n\n const isResultSkipped = (index: number): boolean => {\n return hasRunCompleted.value && getResultAtIndex(index) === null\n }\n\n const getFailedTests = (result: RunResult | null): TestResult[] => {\n if (!result) {\n return []\n }\n return result.testResults.filter((t) => !t.passed)\n }\n\n const getContext = (item: SelectedItem) => {\n const contextResult = getRequestExampleContext(\n workspaceStore,\n documentName,\n { path: item.path, method: item.method, exampleName: item.exampleKey },\n {\n fallbackDocument: document,\n isElectron: isElectron(),\n layout: isWeb ? 'web' : 'other',\n appVersion: APP_VERSION,\n },\n )\n\n return contextResult\n }\n\n const getRequestFactory = (ctx: BuildRequestExampleContext, item: SelectedItem) => {\n const globalCookies = [...ctx.cookies.workspace, ...ctx.cookies.document]\n return requestFactory({\n defaultHeaders: ctx.headers.default,\n environment: ctx.environment.environment,\n exampleName: item.exampleKey,\n globalCookies,\n method: item.method,\n operation: ctx.operation,\n path: item.path,\n proxyUrl: ctx.proxy.url ?? '',\n server: ctx.servers.selected,\n selectedSecuritySchemes: ctx.security.selectedSchemes,\n isElectron: isElectron(),\n })\n }\n\n const run = async () => {\n if (isRunning.value || !document || selectedOrder.value.length === 0) {\n return\n }\n\n isRunning.value = true\n hasRunCompleted.value = false\n runLoader.start()\n runResults.value = []\n currentRunIndex.value = 0\n runStartTime.value = performance.now()\n runEndTime.value = null\n\n const variablesStore = createVariablesStoreForRequest()\n\n // Run each item in the selected order\n for (let i = 0; i < selectedOrder.value.length; i++) {\n currentRunIndex.value = i + 1\n const item = selectedOrder.value[i]!\n\n // Create a run result for the current item\n const runResult: RunResult = {\n item,\n result: null,\n error: null,\n testResults: [],\n }\n\n try {\n const contextResult = getContext(item)\n\n if (!contextResult.ok) {\n runResult.error = new Error(contextResult.error)\n runResults.value = [...runResults.value, runResult]\n continue\n }\n\n const { request: requestBuilder } = getRequestFactory(contextResult.data, item)\n\n const preRequestScript = getScript(document['x-pre-request'], contextResult.data.operation['x-pre-request'])\n await executePreRequestScript(preRequestScript, {\n requestBuilder,\n variablesStore,\n onTestResultsUpdate: (newResults) => {\n runResult.testResults = [...newResults]\n },\n })\n\n const envVariables = {\n ...getEnvironmentVariables(contextResult.data.environment.environment),\n ...variablesStore.getVariables(),\n }\n\n const requestResult = await tryCatch(() => {\n return buildRequest(requestBuilder, { envVariables })\n })\n\n if (!requestResult.ok) {\n runResult.error = new Error(requestResult.error)\n runResults.value = [...runResults.value, runResult]\n continue\n }\n\n const [sendError, sendResult] = await sendRequest({\n isUsingProxy: requestResult.data.isUsingProxy,\n requestPayload: requestResult.data.requestPayload,\n customFetch,\n })\n\n if (sendError) {\n runResult.error = sendError\n runResults.value = [...runResults.value, runResult]\n continue\n }\n\n runResult.result = sendResult.response\n\n const postResponseScript = getScript(\n document['x-post-response'],\n contextResult.data.operation['x-post-response'],\n )\n\n const preRequestResults = [...runResult.testResults]\n await executePostResponseScript(postResponseScript, {\n requestBuilder,\n response: sendResult.originalResponse.clone(),\n variablesStore,\n onTestResultsUpdate: (postResponseResults) => {\n runResult.testResults = [...preRequestResults, ...postResponseResults]\n },\n })\n\n runResults.value = [...runResults.value, runResult]\n\n const hasTestFailure = runResult.testResults.some((t) => !t.passed)\n if (hasTestFailure) {\n break\n }\n } catch (error) {\n runResult.error = error instanceof Error ? error : new Error(String(error))\n runResults.value = [...runResults.value, runResult]\n break\n }\n }\n\n isRunning.value = false\n hasRunCompleted.value = true\n runEndTime.value = performance.now()\n void runLoader.clear()\n currentRunIndex.value = null\n }\n\n return {\n isRunning,\n hasRunCompleted,\n currentRunIndex,\n runLoader,\n runResults,\n runSummary,\n run,\n rerun,\n clearResults,\n getResultAtIndex,\n isResultPassed,\n isResultSkipped,\n getFailedTests,\n }\n}\n"],"mappings":"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"}

@@ -25,2 +25,3 @@ import Section_default from "../../settings/components/Section.vue.js";

onUpdateTelemetry: { type: Function },
options: {},
collectionType: {}

@@ -27,0 +28,0 @@ },

@@ -1,1 +0,1 @@

{"version":3,"file":"Scripts.vue.script.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Scripts.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport DocumentScriptsEditors from '@/v2/features/collection/components/DocumentScriptsEditors.vue'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nconst { document, eventBus, collectionType } = defineProps<CollectionProps>()\n\nconst handleUpdateExtension = (payload: Record<string, unknown>) => {\n eventBus.emit('document:update:extension', payload)\n}\n</script>\n\n<template>\n <Section v-if=\"collectionType === 'document'\">\n <template #title>Pre-request &amp; Post-response Scripts</template>\n <template #description>\n Scripts at the document level run for every request in this document.\n Operation-level scripts (in the request editor) run in addition to these.\n </template>\n <DocumentScriptsEditors\n :document=\"document\"\n @update:extension=\"handleUpdateExtension\" />\n </Section>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;EAOA,MAAM,yBAAyB,YAAqC;AAClE,WAAA,SAAS,KAAK,6BAA6B,QAAO;;;UAKnC,QAAA,mBAAc,cAAA,WAAA,EAA7B,YASU,iBAAA,EAAA,KAAA,GAAA,EAAA;IARG,OAAK,cAAwC,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAAA,gBAAvC,uCAAuC,GAAA,CAAA,EAAA,CAAA;IAC7C,aAAW,cAGtB,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAAA,gBAHuB,qJAGvB,GAAA,CAAA,EAAA,CAAA;2BAG8C,CAF9C,YAE8C,gCAAA;KAD3C,UAAU,QAAA;KACV,sBAAkB"}
{"version":3,"file":"Scripts.vue.script.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Scripts.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport DocumentScriptsEditors from '@/v2/features/collection/components/DocumentScriptsEditors.vue'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nconst { document, eventBus, collectionType } = defineProps<CollectionProps>()\n\nconst handleUpdateExtension = (payload: Record<string, unknown>) => {\n eventBus.emit('document:update:extension', payload)\n}\n</script>\n\n<template>\n <Section v-if=\"collectionType === 'document'\">\n <template #title>Pre-request &amp; Post-response Scripts</template>\n <template #description>\n Scripts at the document level run for every request in this document.\n Operation-level scripts (in the request editor) run in addition to these.\n </template>\n <DocumentScriptsEditors\n :document=\"document\"\n @update:extension=\"handleUpdateExtension\" />\n </Section>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;EAOA,MAAM,yBAAyB,YAAqC;AAClE,WAAA,SAAS,KAAK,6BAA6B,QAAO;;;UAKnC,QAAA,mBAAc,cAAA,WAAA,EAA7B,YASU,iBAAA,EAAA,KAAA,GAAA,EAAA;IARG,OAAK,cAAwC,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAAA,gBAAvC,uCAAuC,GAAA,CAAA,EAAA,CAAA;IAC7C,aAAW,cAGtB,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAAA,gBAHuB,qJAGvB,GAAA,CAAA,EAAA,CAAA;2BAG8C,CAF9C,YAE8C,gCAAA;KAD3C,UAAU,QAAA;KACV,sBAAkB"}

@@ -1,1 +0,1 @@

{"version":3,"file":"Servers.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/collection/components/Servers.vue"],"names":[],"mappings":"AAg0BA,QAAA,MAAM,YAAY;;;;;;;;;;;;kGAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
{"version":3,"file":"Servers.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/collection/components/Servers.vue"],"names":[],"mappings":"AAm0BA,QAAA,MAAM,YAAY;;;;;;;;;;;;kGAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}

@@ -1,1 +0,1 @@

{"version":3,"file":"Servers.vue.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Servers.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarMarkdown,\n ScalarModal,\n ScalarToggle,\n useModal,\n} from '@scalar/components'\nimport { debounce } from '@scalar/helpers/general/debounce'\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport { ScalarIconPlus, ScalarIconTrash } from '@scalar/icons'\nimport type { ServerMeta } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport type { ServerObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, ref, watchEffect } from 'vue'\n\nimport { ServerVariablesForm } from '@/components/Server'\nimport DeleteSidebarListElement from '@/components/Sidebar/Actions/DeleteSidebarListElement.vue'\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nimport Form from './Form.vue'\n\nconst { document, eventBus, collectionType, path, method } =\n defineProps<CollectionProps>()\n\nconst deleteModal = useModal()\nconst selectedServerIndex = ref<number>(-1)\n\nconst isOperation = computed(() => collectionType === 'operation')\n\nconst operation = computed(() => {\n if (!isOperation.value) {\n return null\n }\n // Operation not found\n if (!path || !isHttpMethod(method)) {\n return null\n }\n // Operation found, return the servers\n return getResolvedRef(document?.paths?.[path]?.[method])\n})\n\nconst useOperationServers = ref(false)\nwatchEffect(() => {\n useOperationServers.value = operation.value?.servers !== undefined\n})\n\n/** Grab the servers for the collection */\nconst servers = computed(() => {\n if (collectionType === 'operation' && operation.value) {\n return operation.value.servers ?? []\n }\n return document?.servers ?? []\n})\n\n/** Grab whichever server we are working on */\nconst selectedServer = computed(() => servers.value[selectedServerIndex.value])\n\n/** Meta for server events: document-level or operation-level based on collection type */\nconst serverMeta = computed<ServerMeta>(() => {\n if (collectionType === 'operation' && path && isHttpMethod(method)) {\n return { type: 'operation', path, method }\n }\n return { type: 'document' }\n})\n\n// Form field configuration\nconst FORM_OPTIONS = [\n {\n label: 'URL',\n key: 'url',\n placeholder: 'https://void.scalar.com',\n },\n {\n label: 'Description',\n key: 'description',\n placeholder: 'Production',\n lineWrapping: true,\n },\n]\n\n/** Opens the delete confirmation modal for a server */\nconst openDeleteModal = (index: number) => {\n selectedServerIndex.value = index\n deleteModal.show()\n}\n\n/** Closes the delete modal and resets the selected server */\nconst resetState = () => {\n deleteModal.hide()\n selectedServerIndex.value = -1\n}\n\n/** Handles server deletion */\nconst handleDeleteServer = () => {\n if (selectedServerIndex.value < 0) {\n return\n }\n\n eventBus.emit('server:delete:server', {\n index: selectedServerIndex.value,\n meta: serverMeta.value,\n })\n resetState()\n}\n\n/** Debounced execute function for server updates, keyed so we only debounce by server + key */\nconst { execute } = debounce({ delay: 328, maxWait: 1000 })\n\n/** Handles server property updates with debouncing */\nconst handleServerUpdate = (\n index: number,\n key: string,\n value: string | number,\n) =>\n execute(`${index}-${key}-${serverMeta.value.type}`, () =>\n eventBus.emit('server:update:server', {\n index,\n server: { [key]: value },\n meta: serverMeta.value,\n }),\n )\n\n/** Handles server variable updates with debouncing */\nconst handleVariableUpdate = (index: number, key: string, value: string) =>\n execute(`${index}-${key}-${serverMeta.value.type}`, () =>\n eventBus.emit('server:update:variables', {\n index,\n key,\n value,\n meta: serverMeta.value,\n }),\n )\n\n/** Handles adding a new server */\nconst handleAddServer = () =>\n eventBus.emit('server:add:server', { meta: serverMeta.value })\n\n/**\n * Gets the display name for a server\n */\nconst getServerDisplayName = (server?: ServerObject, index = 0): string =>\n server?.description || `Server ${index + 1}`\n\n/** Handles toggling the operation servers */\nconst handleToggleOperationServers = (value: boolean) => {\n // Only toggle for operation collections\n if (serverMeta.value.type !== 'operation') {\n return\n }\n\n // update the operation servers\n useOperationServers.value = value\n\n if (value) {\n // Initialize the servers with an empty array so we will infer the servers from the operation\n return eventBus.emit('server:initialize:servers', {\n meta: serverMeta.value,\n })\n }\n return eventBus.emit('server:clear:servers', { meta: serverMeta.value })\n}\n</script>\n\n<template>\n <Section>\n <template #title>Servers</template>\n <template #description>\n <template v-if=\"isOperation\">\n <span class=\"block\">\n Override servers for this operation with the toggle.\n </span>\n <span class=\"mt-1 block\">\n <strong>On</strong> — Servers below apply only to this operation.\n </span>\n <span class=\"mt-1 block\">\n <strong>Off</strong> — Removes operation servers; this operation uses\n document or path servers from the OpenAPI spec.\n </span>\n <span class=\"text-c-3 mt-1 block\">\n Use <code class=\"font-code text-c-2\">{variables}</code> for dynamic\n URL parts.\n </span>\n </template>\n <template v-else>\n Add different base URLs for your API. Use\n <code class=\"font-code text-c-2\">{variables}</code> for dynamic parts.\n </template>\n </template>\n <!-- Operation Servers Toggle to use the operation servers instead of the document servers -->\n <template\n v-if=\"isOperation\"\n #actions>\n <div class=\"flex h-8 items-center\">\n <ScalarToggle\n class=\"w-4\"\n :modelValue=\"useOperationServers\"\n @update:modelValue=\"handleToggleOperationServers\" />\n </div>\n </template>\n\n <div :class=\"isOperation && !useOperationServers && 'cursor-not-allowed'\">\n <div\n class=\"flex flex-col gap-4\"\n :class=\"\n isOperation &&\n !useOperationServers &&\n 'pointer-events-none cursor-not-allowed opacity-50 mix-blend-luminosity'\n \">\n <!-- Server List -->\n <div class=\"flex flex-col gap-4\">\n <div\n v-for=\"(server, index) in servers\"\n :key=\"index\"\n class=\"rounded-lg border\">\n <!-- Server Header -->\n <div\n class=\"bg-b-2 flex items-center justify-between rounded-t-lg px-3 py-1 text-sm\">\n <ScalarMarkdown\n v-if=\"server.description\"\n class=\"self-center\"\n :value=\"server.description\" />\n <span\n v-else\n class=\"self-center\">\n {{ getServerDisplayName(server, index) }}\n </span>\n <ScalarButton\n class=\"hover:bg-b-3 hover:text-c-1 h-fit p-1.25\"\n data-testid=\"delete-server-button\"\n variant=\"ghost\"\n @click=\"openDeleteModal(index)\">\n <ScalarIconTrash class=\"size-3.5\" />\n </ScalarButton>\n </div>\n\n <!-- Server Variables Form -->\n <div\n class=\"divide-0 flex w-full flex-col divide-y rounded-b-lg text-sm\">\n <Form\n :data=\"server\"\n :environment=\"environment\"\n :onUpdate=\"\n (key, value) => handleServerUpdate(index, key, value)\n \"\n :options=\"FORM_OPTIONS\" />\n <ServerVariablesForm\n v-if=\"server.variables\"\n :variables=\"server.variables\"\n @update:variable=\"\n (name, value) => handleVariableUpdate(index, name, value)\n \" />\n </div>\n </div>\n </div>\n\n <!-- Add Server Button -->\n <div\n class=\"text-c-3 flex h-full items-center justify-center rounded-lg border p-4\">\n <ScalarButton\n class=\"hover:bg-b-2 hover:text-c-1 flex items-center gap-2\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"handleAddServer\">\n <ScalarIconPlus />\n <span>Add Server</span>\n </ScalarButton>\n </div>\n </div>\n </div>\n </Section>\n\n <!-- Delete Confirmation Modal -->\n <ScalarModal\n size=\"xxs\"\n :state=\"deleteModal\"\n :title=\"`Delete ${getServerDisplayName(selectedServer, selectedServerIndex)}`\">\n <DeleteSidebarListElement\n variableName=\"Server\"\n warningMessage=\"Are you sure you want to delete this server? This action cannot be undone.\"\n @close=\"resetState\"\n @delete=\"handleDeleteServer\" />\n </ScalarModal>\n</template>\n"],"mappings":""}
{"version":3,"file":"Servers.vue.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Servers.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarMarkdown,\n ScalarModal,\n ScalarToggle,\n useModal,\n} from '@scalar/components'\nimport { debounce } from '@scalar/helpers/general/debounce'\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport { ScalarIconPlus, ScalarIconTrash } from '@scalar/icons'\nimport type { ServerMeta } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport type { ServerObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, ref, watchEffect } from 'vue'\n\nimport { ServerVariablesForm } from '@/components/Server'\nimport DeleteSidebarListElement from '@/components/Sidebar/Actions/DeleteSidebarListElement.vue'\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nimport Form from './Form.vue'\n\nconst { document, eventBus, collectionType, path, method } =\n defineProps<CollectionProps>()\n\nconst deleteModal = useModal()\nconst selectedServerIndex = ref<number>(-1)\n\nconst isOperation = computed(() => collectionType === 'operation')\n\nconst operation = computed(() => {\n if (!isOperation.value) {\n return null\n }\n // Operation not found\n if (!path || !isHttpMethod(method)) {\n return null\n }\n // Operation found, return the servers\n return getResolvedRef(document?.paths?.[path]?.[method])\n})\n\nconst useOperationServers = ref(false)\nwatchEffect(() => {\n useOperationServers.value = operation.value?.servers !== undefined\n})\n\n/** Grab the servers for the collection */\nconst servers = computed(() => {\n if (collectionType === 'operation' && operation.value) {\n return operation.value.servers ?? []\n }\n return document?.servers ?? []\n})\n\n/** Grab whichever server we are working on */\nconst selectedServer = computed(() => servers.value[selectedServerIndex.value])\n\n/** Meta for server events: document-level or operation-level based on collection type */\nconst serverMeta = computed<ServerMeta>(() => {\n if (collectionType === 'operation' && path && isHttpMethod(method)) {\n return { type: 'operation', path, method }\n }\n return { type: 'document' }\n})\n\n// Form field configuration\nconst FORM_OPTIONS = [\n {\n label: 'URL',\n key: 'url',\n placeholder: 'https://void.scalar.com',\n },\n {\n label: 'Description',\n key: 'description',\n placeholder: 'Production',\n lineWrapping: true,\n },\n]\n\n/** Opens the delete confirmation modal for a server */\nconst openDeleteModal = (index: number) => {\n selectedServerIndex.value = index\n deleteModal.show()\n}\n\n/** Closes the delete modal and resets the selected server */\nconst resetState = () => {\n deleteModal.hide()\n selectedServerIndex.value = -1\n}\n\n/** Handles server deletion */\nconst handleDeleteServer = () => {\n if (selectedServerIndex.value < 0) {\n return\n }\n\n eventBus.emit('server:delete:server', {\n index: selectedServerIndex.value,\n meta: serverMeta.value,\n })\n resetState()\n}\n\n/** Debounced execute function for server updates, keyed so we only debounce by server + key */\nconst { execute } = debounce({ delay: 328, maxWait: 1000 })\n\n/** Handles server property updates with debouncing */\nconst handleServerUpdate = (\n index: number,\n key: string,\n value: string | number,\n) =>\n execute(`${index}-${key}-${serverMeta.value.type}`, () =>\n eventBus.emit('server:update:server', {\n index,\n server: { [key]: value },\n meta: serverMeta.value,\n }),\n )\n\n/** Handles server variable updates with debouncing */\nconst handleVariableUpdate = (index: number, key: string, value: string) =>\n execute(`${index}-${key}-${serverMeta.value.type}`, () =>\n eventBus.emit('server:update:variables', {\n index,\n key,\n value,\n meta: serverMeta.value,\n }),\n )\n\n/** Handles adding a new server */\nconst handleAddServer = () =>\n eventBus.emit('server:add:server', { meta: serverMeta.value })\n\n/**\n * Gets the display name for a server\n */\nconst getServerDisplayName = (server?: ServerObject, index = 0): string =>\n server?.description || `Server ${index + 1}`\n\n/** Handles toggling the operation servers */\nconst handleToggleOperationServers = (value: boolean) => {\n // Only toggle for operation collections\n if (serverMeta.value.type !== 'operation') {\n return\n }\n\n // update the operation servers\n useOperationServers.value = value\n\n if (value) {\n // Initialize the servers with an empty array so we will infer the servers from the operation\n return eventBus.emit('server:initialize:servers', {\n meta: serverMeta.value,\n })\n }\n return eventBus.emit('server:clear:servers', { meta: serverMeta.value })\n}\n</script>\n\n<template>\n <Section>\n <template #title>Servers</template>\n <template #description>\n <template v-if=\"isOperation\">\n <span class=\"block\">\n Override servers for this operation with the toggle.\n </span>\n <span class=\"mt-1 block\">\n <strong>On</strong> — Servers below apply only to this operation.\n </span>\n <span class=\"mt-1 block\">\n <strong>Off</strong> — Removes operation servers; this operation uses\n document or path servers from the OpenAPI spec.\n </span>\n <span class=\"text-c-3 mt-1 block\">\n Use <code class=\"font-code text-c-2\">{variables}</code> for dynamic\n URL parts.\n </span>\n </template>\n <template v-else>\n Add different base URLs for your API. Use\n <code class=\"font-code text-c-2\">{variables}</code> for dynamic parts.\n </template>\n </template>\n <!-- Operation Servers Toggle to use the operation servers instead of the document servers -->\n <template\n v-if=\"isOperation\"\n #actions>\n <div class=\"flex h-8 items-center\">\n <ScalarToggle\n class=\"w-4\"\n :modelValue=\"useOperationServers\"\n @update:modelValue=\"handleToggleOperationServers\" />\n </div>\n </template>\n\n <div :class=\"isOperation && !useOperationServers && 'cursor-not-allowed'\">\n <div\n class=\"flex flex-col gap-4\"\n :class=\"\n isOperation &&\n !useOperationServers &&\n 'pointer-events-none cursor-not-allowed opacity-50 mix-blend-luminosity'\n \">\n <!-- Server List -->\n <div class=\"flex flex-col gap-4\">\n <div\n v-for=\"(server, index) in servers\"\n :key=\"index\"\n class=\"rounded-lg border\">\n <!-- Server Header -->\n <div\n class=\"bg-b-2 flex items-center justify-between rounded-t-lg px-3 py-1 text-sm\">\n <ScalarMarkdown\n v-if=\"server.description\"\n class=\"self-center\"\n :value=\"server.description\" />\n <span\n v-else\n class=\"self-center\">\n {{ getServerDisplayName(server, index) }}\n </span>\n <ScalarButton\n class=\"hover:bg-b-3 hover:text-c-1 h-fit p-1.25\"\n data-testid=\"delete-server-button\"\n variant=\"ghost\"\n @click=\"openDeleteModal(index)\">\n <ScalarIconTrash class=\"size-3.5\" />\n </ScalarButton>\n </div>\n\n <!-- Server Variables Form -->\n <div\n class=\"divide-0 flex w-full flex-col divide-y rounded-b-lg text-sm\">\n <Form\n :data=\"server\"\n :environment=\"environment\"\n :onUpdate=\"\n (key, value) => handleServerUpdate(index, key, value)\n \"\n :options=\"FORM_OPTIONS\"\n :withFakeData=\"false\" />\n <ServerVariablesForm\n v-if=\"server.variables\"\n :variables=\"server.variables\"\n @update:variable=\"\n (name, value) => handleVariableUpdate(index, name, value)\n \" />\n </div>\n </div>\n </div>\n\n <!-- Add Server Button -->\n <div\n class=\"text-c-3 flex h-full items-center justify-center rounded-lg border p-4\">\n <ScalarButton\n class=\"hover:bg-b-2 hover:text-c-1 flex items-center gap-2\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"handleAddServer\">\n <ScalarIconPlus />\n <span>Add Server</span>\n </ScalarButton>\n </div>\n </div>\n </div>\n </Section>\n\n <!-- Delete Confirmation Modal -->\n <ScalarModal\n size=\"xxs\"\n :state=\"deleteModal\"\n :title=\"`Delete ${getServerDisplayName(selectedServer, selectedServerIndex)}`\">\n <DeleteSidebarListElement\n variableName=\"Server\"\n warningMessage=\"Are you sure you want to delete this server? This action cannot be undone.\"\n @close=\"resetState\"\n @delete=\"handleDeleteServer\" />\n </ScalarModal>\n</template>\n"],"mappings":""}

@@ -41,2 +41,3 @@ import ServerVariablesForm_default from "../../../../components/Server/ServerVariablesForm.vue.js";

onUpdateTelemetry: { type: Function },
options: {},
collectionType: {}

@@ -170,3 +171,4 @@ },

onUpdate: (key, value) => handleServerUpdate(index, key, value),
options: FORM_OPTIONS
options: FORM_OPTIONS,
withFakeData: false
}, null, 8, [

@@ -173,0 +175,0 @@ "data",

@@ -1,1 +0,1 @@

{"version":3,"file":"Servers.vue.script.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Servers.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarMarkdown,\n ScalarModal,\n ScalarToggle,\n useModal,\n} from '@scalar/components'\nimport { debounce } from '@scalar/helpers/general/debounce'\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport { ScalarIconPlus, ScalarIconTrash } from '@scalar/icons'\nimport type { ServerMeta } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport type { ServerObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, ref, watchEffect } from 'vue'\n\nimport { ServerVariablesForm } from '@/components/Server'\nimport DeleteSidebarListElement from '@/components/Sidebar/Actions/DeleteSidebarListElement.vue'\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nimport Form from './Form.vue'\n\nconst { document, eventBus, collectionType, path, method } =\n defineProps<CollectionProps>()\n\nconst deleteModal = useModal()\nconst selectedServerIndex = ref<number>(-1)\n\nconst isOperation = computed(() => collectionType === 'operation')\n\nconst operation = computed(() => {\n if (!isOperation.value) {\n return null\n }\n // Operation not found\n if (!path || !isHttpMethod(method)) {\n return null\n }\n // Operation found, return the servers\n return getResolvedRef(document?.paths?.[path]?.[method])\n})\n\nconst useOperationServers = ref(false)\nwatchEffect(() => {\n useOperationServers.value = operation.value?.servers !== undefined\n})\n\n/** Grab the servers for the collection */\nconst servers = computed(() => {\n if (collectionType === 'operation' && operation.value) {\n return operation.value.servers ?? []\n }\n return document?.servers ?? []\n})\n\n/** Grab whichever server we are working on */\nconst selectedServer = computed(() => servers.value[selectedServerIndex.value])\n\n/** Meta for server events: document-level or operation-level based on collection type */\nconst serverMeta = computed<ServerMeta>(() => {\n if (collectionType === 'operation' && path && isHttpMethod(method)) {\n return { type: 'operation', path, method }\n }\n return { type: 'document' }\n})\n\n// Form field configuration\nconst FORM_OPTIONS = [\n {\n label: 'URL',\n key: 'url',\n placeholder: 'https://void.scalar.com',\n },\n {\n label: 'Description',\n key: 'description',\n placeholder: 'Production',\n lineWrapping: true,\n },\n]\n\n/** Opens the delete confirmation modal for a server */\nconst openDeleteModal = (index: number) => {\n selectedServerIndex.value = index\n deleteModal.show()\n}\n\n/** Closes the delete modal and resets the selected server */\nconst resetState = () => {\n deleteModal.hide()\n selectedServerIndex.value = -1\n}\n\n/** Handles server deletion */\nconst handleDeleteServer = () => {\n if (selectedServerIndex.value < 0) {\n return\n }\n\n eventBus.emit('server:delete:server', {\n index: selectedServerIndex.value,\n meta: serverMeta.value,\n })\n resetState()\n}\n\n/** Debounced execute function for server updates, keyed so we only debounce by server + key */\nconst { execute } = debounce({ delay: 328, maxWait: 1000 })\n\n/** Handles server property updates with debouncing */\nconst handleServerUpdate = (\n index: number,\n key: string,\n value: string | number,\n) =>\n execute(`${index}-${key}-${serverMeta.value.type}`, () =>\n eventBus.emit('server:update:server', {\n index,\n server: { [key]: value },\n meta: serverMeta.value,\n }),\n )\n\n/** Handles server variable updates with debouncing */\nconst handleVariableUpdate = (index: number, key: string, value: string) =>\n execute(`${index}-${key}-${serverMeta.value.type}`, () =>\n eventBus.emit('server:update:variables', {\n index,\n key,\n value,\n meta: serverMeta.value,\n }),\n )\n\n/** Handles adding a new server */\nconst handleAddServer = () =>\n eventBus.emit('server:add:server', { meta: serverMeta.value })\n\n/**\n * Gets the display name for a server\n */\nconst getServerDisplayName = (server?: ServerObject, index = 0): string =>\n server?.description || `Server ${index + 1}`\n\n/** Handles toggling the operation servers */\nconst handleToggleOperationServers = (value: boolean) => {\n // Only toggle for operation collections\n if (serverMeta.value.type !== 'operation') {\n return\n }\n\n // update the operation servers\n useOperationServers.value = value\n\n if (value) {\n // Initialize the servers with an empty array so we will infer the servers from the operation\n return eventBus.emit('server:initialize:servers', {\n meta: serverMeta.value,\n })\n }\n return eventBus.emit('server:clear:servers', { meta: serverMeta.value })\n}\n</script>\n\n<template>\n <Section>\n <template #title>Servers</template>\n <template #description>\n <template v-if=\"isOperation\">\n <span class=\"block\">\n Override servers for this operation with the toggle.\n </span>\n <span class=\"mt-1 block\">\n <strong>On</strong> — Servers below apply only to this operation.\n </span>\n <span class=\"mt-1 block\">\n <strong>Off</strong> — Removes operation servers; this operation uses\n document or path servers from the OpenAPI spec.\n </span>\n <span class=\"text-c-3 mt-1 block\">\n Use <code class=\"font-code text-c-2\">{variables}</code> for dynamic\n URL parts.\n </span>\n </template>\n <template v-else>\n Add different base URLs for your API. Use\n <code class=\"font-code text-c-2\">{variables}</code> for dynamic parts.\n </template>\n </template>\n <!-- Operation Servers Toggle to use the operation servers instead of the document servers -->\n <template\n v-if=\"isOperation\"\n #actions>\n <div class=\"flex h-8 items-center\">\n <ScalarToggle\n class=\"w-4\"\n :modelValue=\"useOperationServers\"\n @update:modelValue=\"handleToggleOperationServers\" />\n </div>\n </template>\n\n <div :class=\"isOperation && !useOperationServers && 'cursor-not-allowed'\">\n <div\n class=\"flex flex-col gap-4\"\n :class=\"\n isOperation &&\n !useOperationServers &&\n 'pointer-events-none cursor-not-allowed opacity-50 mix-blend-luminosity'\n \">\n <!-- Server List -->\n <div class=\"flex flex-col gap-4\">\n <div\n v-for=\"(server, index) in servers\"\n :key=\"index\"\n class=\"rounded-lg border\">\n <!-- Server Header -->\n <div\n class=\"bg-b-2 flex items-center justify-between rounded-t-lg px-3 py-1 text-sm\">\n <ScalarMarkdown\n v-if=\"server.description\"\n class=\"self-center\"\n :value=\"server.description\" />\n <span\n v-else\n class=\"self-center\">\n {{ getServerDisplayName(server, index) }}\n </span>\n <ScalarButton\n class=\"hover:bg-b-3 hover:text-c-1 h-fit p-1.25\"\n data-testid=\"delete-server-button\"\n variant=\"ghost\"\n @click=\"openDeleteModal(index)\">\n <ScalarIconTrash class=\"size-3.5\" />\n </ScalarButton>\n </div>\n\n <!-- Server Variables Form -->\n <div\n class=\"divide-0 flex w-full flex-col divide-y rounded-b-lg text-sm\">\n <Form\n :data=\"server\"\n :environment=\"environment\"\n :onUpdate=\"\n (key, value) => handleServerUpdate(index, key, value)\n \"\n :options=\"FORM_OPTIONS\" />\n <ServerVariablesForm\n v-if=\"server.variables\"\n :variables=\"server.variables\"\n @update:variable=\"\n (name, value) => handleVariableUpdate(index, name, value)\n \" />\n </div>\n </div>\n </div>\n\n <!-- Add Server Button -->\n <div\n class=\"text-c-3 flex h-full items-center justify-center rounded-lg border p-4\">\n <ScalarButton\n class=\"hover:bg-b-2 hover:text-c-1 flex items-center gap-2\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"handleAddServer\">\n <ScalarIconPlus />\n <span>Add Server</span>\n </ScalarButton>\n </div>\n </div>\n </div>\n </Section>\n\n <!-- Delete Confirmation Modal -->\n <ScalarModal\n size=\"xxs\"\n :state=\"deleteModal\"\n :title=\"`Delete ${getServerDisplayName(selectedServer, selectedServerIndex)}`\">\n <DeleteSidebarListElement\n variableName=\"Server\"\n warningMessage=\"Are you sure you want to delete this server? This action cannot be undone.\"\n @close=\"resetState\"\n @delete=\"handleDeleteServer\" />\n </ScalarModal>\n</template>\n"],"mappings":"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"}
{"version":3,"file":"Servers.vue.script.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Servers.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarMarkdown,\n ScalarModal,\n ScalarToggle,\n useModal,\n} from '@scalar/components'\nimport { debounce } from '@scalar/helpers/general/debounce'\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport { ScalarIconPlus, ScalarIconTrash } from '@scalar/icons'\nimport type { ServerMeta } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport type { ServerObject } from '@scalar/workspace-store/schemas/v3.1/strict/openapi-document'\nimport { computed, ref, watchEffect } from 'vue'\n\nimport { ServerVariablesForm } from '@/components/Server'\nimport DeleteSidebarListElement from '@/components/Sidebar/Actions/DeleteSidebarListElement.vue'\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nimport Form from './Form.vue'\n\nconst { document, eventBus, collectionType, path, method } =\n defineProps<CollectionProps>()\n\nconst deleteModal = useModal()\nconst selectedServerIndex = ref<number>(-1)\n\nconst isOperation = computed(() => collectionType === 'operation')\n\nconst operation = computed(() => {\n if (!isOperation.value) {\n return null\n }\n // Operation not found\n if (!path || !isHttpMethod(method)) {\n return null\n }\n // Operation found, return the servers\n return getResolvedRef(document?.paths?.[path]?.[method])\n})\n\nconst useOperationServers = ref(false)\nwatchEffect(() => {\n useOperationServers.value = operation.value?.servers !== undefined\n})\n\n/** Grab the servers for the collection */\nconst servers = computed(() => {\n if (collectionType === 'operation' && operation.value) {\n return operation.value.servers ?? []\n }\n return document?.servers ?? []\n})\n\n/** Grab whichever server we are working on */\nconst selectedServer = computed(() => servers.value[selectedServerIndex.value])\n\n/** Meta for server events: document-level or operation-level based on collection type */\nconst serverMeta = computed<ServerMeta>(() => {\n if (collectionType === 'operation' && path && isHttpMethod(method)) {\n return { type: 'operation', path, method }\n }\n return { type: 'document' }\n})\n\n// Form field configuration\nconst FORM_OPTIONS = [\n {\n label: 'URL',\n key: 'url',\n placeholder: 'https://void.scalar.com',\n },\n {\n label: 'Description',\n key: 'description',\n placeholder: 'Production',\n lineWrapping: true,\n },\n]\n\n/** Opens the delete confirmation modal for a server */\nconst openDeleteModal = (index: number) => {\n selectedServerIndex.value = index\n deleteModal.show()\n}\n\n/** Closes the delete modal and resets the selected server */\nconst resetState = () => {\n deleteModal.hide()\n selectedServerIndex.value = -1\n}\n\n/** Handles server deletion */\nconst handleDeleteServer = () => {\n if (selectedServerIndex.value < 0) {\n return\n }\n\n eventBus.emit('server:delete:server', {\n index: selectedServerIndex.value,\n meta: serverMeta.value,\n })\n resetState()\n}\n\n/** Debounced execute function for server updates, keyed so we only debounce by server + key */\nconst { execute } = debounce({ delay: 328, maxWait: 1000 })\n\n/** Handles server property updates with debouncing */\nconst handleServerUpdate = (\n index: number,\n key: string,\n value: string | number,\n) =>\n execute(`${index}-${key}-${serverMeta.value.type}`, () =>\n eventBus.emit('server:update:server', {\n index,\n server: { [key]: value },\n meta: serverMeta.value,\n }),\n )\n\n/** Handles server variable updates with debouncing */\nconst handleVariableUpdate = (index: number, key: string, value: string) =>\n execute(`${index}-${key}-${serverMeta.value.type}`, () =>\n eventBus.emit('server:update:variables', {\n index,\n key,\n value,\n meta: serverMeta.value,\n }),\n )\n\n/** Handles adding a new server */\nconst handleAddServer = () =>\n eventBus.emit('server:add:server', { meta: serverMeta.value })\n\n/**\n * Gets the display name for a server\n */\nconst getServerDisplayName = (server?: ServerObject, index = 0): string =>\n server?.description || `Server ${index + 1}`\n\n/** Handles toggling the operation servers */\nconst handleToggleOperationServers = (value: boolean) => {\n // Only toggle for operation collections\n if (serverMeta.value.type !== 'operation') {\n return\n }\n\n // update the operation servers\n useOperationServers.value = value\n\n if (value) {\n // Initialize the servers with an empty array so we will infer the servers from the operation\n return eventBus.emit('server:initialize:servers', {\n meta: serverMeta.value,\n })\n }\n return eventBus.emit('server:clear:servers', { meta: serverMeta.value })\n}\n</script>\n\n<template>\n <Section>\n <template #title>Servers</template>\n <template #description>\n <template v-if=\"isOperation\">\n <span class=\"block\">\n Override servers for this operation with the toggle.\n </span>\n <span class=\"mt-1 block\">\n <strong>On</strong> — Servers below apply only to this operation.\n </span>\n <span class=\"mt-1 block\">\n <strong>Off</strong> — Removes operation servers; this operation uses\n document or path servers from the OpenAPI spec.\n </span>\n <span class=\"text-c-3 mt-1 block\">\n Use <code class=\"font-code text-c-2\">{variables}</code> for dynamic\n URL parts.\n </span>\n </template>\n <template v-else>\n Add different base URLs for your API. Use\n <code class=\"font-code text-c-2\">{variables}</code> for dynamic parts.\n </template>\n </template>\n <!-- Operation Servers Toggle to use the operation servers instead of the document servers -->\n <template\n v-if=\"isOperation\"\n #actions>\n <div class=\"flex h-8 items-center\">\n <ScalarToggle\n class=\"w-4\"\n :modelValue=\"useOperationServers\"\n @update:modelValue=\"handleToggleOperationServers\" />\n </div>\n </template>\n\n <div :class=\"isOperation && !useOperationServers && 'cursor-not-allowed'\">\n <div\n class=\"flex flex-col gap-4\"\n :class=\"\n isOperation &&\n !useOperationServers &&\n 'pointer-events-none cursor-not-allowed opacity-50 mix-blend-luminosity'\n \">\n <!-- Server List -->\n <div class=\"flex flex-col gap-4\">\n <div\n v-for=\"(server, index) in servers\"\n :key=\"index\"\n class=\"rounded-lg border\">\n <!-- Server Header -->\n <div\n class=\"bg-b-2 flex items-center justify-between rounded-t-lg px-3 py-1 text-sm\">\n <ScalarMarkdown\n v-if=\"server.description\"\n class=\"self-center\"\n :value=\"server.description\" />\n <span\n v-else\n class=\"self-center\">\n {{ getServerDisplayName(server, index) }}\n </span>\n <ScalarButton\n class=\"hover:bg-b-3 hover:text-c-1 h-fit p-1.25\"\n data-testid=\"delete-server-button\"\n variant=\"ghost\"\n @click=\"openDeleteModal(index)\">\n <ScalarIconTrash class=\"size-3.5\" />\n </ScalarButton>\n </div>\n\n <!-- Server Variables Form -->\n <div\n class=\"divide-0 flex w-full flex-col divide-y rounded-b-lg text-sm\">\n <Form\n :data=\"server\"\n :environment=\"environment\"\n :onUpdate=\"\n (key, value) => handleServerUpdate(index, key, value)\n \"\n :options=\"FORM_OPTIONS\"\n :withFakeData=\"false\" />\n <ServerVariablesForm\n v-if=\"server.variables\"\n :variables=\"server.variables\"\n @update:variable=\"\n (name, value) => handleVariableUpdate(index, name, value)\n \" />\n </div>\n </div>\n </div>\n\n <!-- Add Server Button -->\n <div\n class=\"text-c-3 flex h-full items-center justify-center rounded-lg border p-4\">\n <ScalarButton\n class=\"hover:bg-b-2 hover:text-c-1 flex items-center gap-2\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"handleAddServer\">\n <ScalarIconPlus />\n <span>Add Server</span>\n </ScalarButton>\n </div>\n </div>\n </div>\n </Section>\n\n <!-- Delete Confirmation Modal -->\n <ScalarModal\n size=\"xxs\"\n :state=\"deleteModal\"\n :title=\"`Delete ${getServerDisplayName(selectedServer, selectedServerIndex)}`\">\n <DeleteSidebarListElement\n variableName=\"Server\"\n warningMessage=\"Are you sure you want to delete this server? This action cannot be undone.\"\n @close=\"resetState\"\n @delete=\"handleDeleteServer\" />\n </ScalarModal>\n</template>\n"],"mappings":"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"}

@@ -26,2 +26,3 @@ import CollectionSettings_default from "../../settings/CollectionSettings.vue.js";

onUpdateTelemetry: { type: Function },
options: {},
collectionType: {}

@@ -28,0 +29,0 @@ },

@@ -1,1 +0,1 @@

{"version":3,"file":"Settings.vue.script.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Settings.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { getActiveProxyUrl } from '@scalar/workspace-store/request-example'\nimport type { ColorMode } from '@scalar/workspace-store/schemas/workspace'\n\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { CollectionSettings, DocumentSettings } from '@/v2/features/settings'\n\nconst {\n eventBus,\n documentSlug,\n document,\n workspaceStore,\n collectionType,\n layout,\n telemetry,\n onUpdateTelemetry,\n} = defineProps<CollectionProps>()\n\nconst handleUpdateWatchMode = (watchMode: boolean) => {\n eventBus.emit('document:update:watch-mode', watchMode)\n}\n\nconst handleUpdateThemeSlug = (themeSlug?: string) => {\n eventBus.emit('workspace:update:theme', themeSlug)\n}\nconst handleUpdateActiveProxy = (proxy: string | null) => {\n eventBus.emit('workspace:update:active-proxy', proxy)\n}\n\nconst handleUpdateColorMode = (colorMode: ColorMode) => {\n eventBus.emit('workspace:update:color-mode', colorMode)\n}\n</script>\n<template>\n <DocumentSettings\n v-if=\"collectionType === 'document'\"\n :documentUrl=\"document?.['x-scalar-original-source-url']\"\n :isDraftDocument=\"documentSlug === 'drafts'\"\n :title=\"document?.info.title ?? ''\"\n :watchMode=\"document?.['x-scalar-watch-mode']\"\n @delete:document=\"\n eventBus.emit('document:delete:document', { name: documentSlug })\n \"\n @update:watchMode=\"handleUpdateWatchMode\" />\n <CollectionSettings\n v-else\n :activeProxyUrl=\"\n getActiveProxyUrl(\n workspaceStore.workspace['x-scalar-active-proxy'],\n layout === 'web' ? 'web' : 'other',\n )\n \"\n :activeThemeSlug=\"workspaceStore.workspace['x-scalar-theme'] ?? 'none'\"\n :colorMode=\"workspaceStore.workspace['x-scalar-color-mode'] ?? 'system'\"\n :customThemes=\"customThemes\"\n :telemetry=\"telemetry\"\n @update:colorMode=\"handleUpdateColorMode\"\n @update:proxyUrl=\"handleUpdateActiveProxy\"\n @update:telemetry=\"(value) => onUpdateTelemetry?.(value)\"\n @update:themeSlug=\"handleUpdateThemeSlug\" />\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkBA,MAAM,yBAAyB,cAAuB;AACpD,WAAA,SAAS,KAAK,8BAA8B,UAAS;;EAGvD,MAAM,yBAAyB,cAAuB;AACpD,WAAA,SAAS,KAAK,0BAA0B,UAAS;;EAEnD,MAAM,2BAA2B,UAAyB;AACxD,WAAA,SAAS,KAAK,iCAAiC,MAAK;;EAGtD,MAAM,yBAAyB,cAAyB;AACtD,WAAA,SAAS,KAAK,+BAA+B,UAAS;;;UAK9C,QAAA,mBAAc,cAAA,WAAA,EADtB,YAS8C,MAAA,yBAAA,EAAA;;IAP3C,aAAa,QAAA,WAAQ;IACrB,iBAAiB,QAAA,iBAAY;IAC7B,OAAO,QAAA,UAAU,KAAK,SAAK;IAC3B,WAAW,QAAA,WAAQ;IACnB,qBAAe,OAAA,OAAA,OAAA,MAAA,WAAS,QAAA,SAAS,KAAI,4BAAA,EAAA,MAAqC,QAAA,cAAY,CAAA;IAGtF,sBAAkB;;;;;;uBACrB,YAe8C,MAAA,2BAAA,EAAA;;IAb3C,gBAAuB,MAAA,kBAAiB,CAAU,QAAA,eAAe,UAAS,0BAAmC,QAAA,WAAM,QAAA,QAAA,QAAA;IAMnH,iBAAiB,QAAA,eAAe,UAAS,qBAAA;IACzC,WAAW,QAAA,eAAe,UAAS,0BAAA;IACnC,cAAc,QAAA;IACd,WAAW,QAAA;IACX,sBAAkB;IAClB,qBAAiB;IACjB,sBAAgB,OAAA,OAAA,OAAA,MAAG,UAAU,QAAA,oBAAoB,MAAK;IACtD,sBAAkB"}
{"version":3,"file":"Settings.vue.script.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Settings.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { getActiveProxyUrl } from '@scalar/workspace-store/request-example'\nimport type { ColorMode } from '@scalar/workspace-store/schemas/workspace'\n\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { CollectionSettings, DocumentSettings } from '@/v2/features/settings'\n\nconst {\n eventBus,\n documentSlug,\n document,\n workspaceStore,\n collectionType,\n layout,\n telemetry,\n onUpdateTelemetry,\n} = defineProps<CollectionProps>()\n\nconst handleUpdateWatchMode = (watchMode: boolean) => {\n eventBus.emit('document:update:watch-mode', watchMode)\n}\n\nconst handleUpdateThemeSlug = (themeSlug?: string) => {\n eventBus.emit('workspace:update:theme', themeSlug)\n}\nconst handleUpdateActiveProxy = (proxy: string | null) => {\n eventBus.emit('workspace:update:active-proxy', proxy)\n}\n\nconst handleUpdateColorMode = (colorMode: ColorMode) => {\n eventBus.emit('workspace:update:color-mode', colorMode)\n}\n</script>\n<template>\n <DocumentSettings\n v-if=\"collectionType === 'document'\"\n :documentUrl=\"document?.['x-scalar-original-source-url']\"\n :isDraftDocument=\"documentSlug === 'drafts'\"\n :title=\"document?.info.title ?? ''\"\n :watchMode=\"document?.['x-scalar-watch-mode']\"\n @delete:document=\"\n eventBus.emit('document:delete:document', { name: documentSlug })\n \"\n @update:watchMode=\"handleUpdateWatchMode\" />\n <CollectionSettings\n v-else\n :activeProxyUrl=\"\n getActiveProxyUrl(\n workspaceStore.workspace['x-scalar-active-proxy'],\n layout === 'web' ? 'web' : 'other',\n )\n \"\n :activeThemeSlug=\"workspaceStore.workspace['x-scalar-theme'] ?? 'none'\"\n :colorMode=\"workspaceStore.workspace['x-scalar-color-mode'] ?? 'system'\"\n :customThemes=\"customThemes\"\n :telemetry=\"telemetry\"\n @update:colorMode=\"handleUpdateColorMode\"\n @update:proxyUrl=\"handleUpdateActiveProxy\"\n @update:telemetry=\"(value) => onUpdateTelemetry?.(value)\"\n @update:themeSlug=\"handleUpdateThemeSlug\" />\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkBA,MAAM,yBAAyB,cAAuB;AACpD,WAAA,SAAS,KAAK,8BAA8B,UAAS;;EAGvD,MAAM,yBAAyB,cAAuB;AACpD,WAAA,SAAS,KAAK,0BAA0B,UAAS;;EAEnD,MAAM,2BAA2B,UAAyB;AACxD,WAAA,SAAS,KAAK,iCAAiC,MAAK;;EAGtD,MAAM,yBAAyB,cAAyB;AACtD,WAAA,SAAS,KAAK,+BAA+B,UAAS;;;UAK9C,QAAA,mBAAc,cAAA,WAAA,EADtB,YAS8C,MAAA,yBAAA,EAAA;;IAP3C,aAAa,QAAA,WAAQ;IACrB,iBAAiB,QAAA,iBAAY;IAC7B,OAAO,QAAA,UAAU,KAAK,SAAK;IAC3B,WAAW,QAAA,WAAQ;IACnB,qBAAe,OAAA,OAAA,OAAA,MAAA,WAAS,QAAA,SAAS,KAAI,4BAAA,EAAA,MAAqC,QAAA,cAAY,CAAA;IAGtF,sBAAkB;;;;;;uBACrB,YAe8C,MAAA,2BAAA,EAAA;;IAb3C,gBAAuB,MAAA,kBAAiB,CAAU,QAAA,eAAe,UAAS,0BAAmC,QAAA,WAAM,QAAA,QAAA,QAAA;IAMnH,iBAAiB,QAAA,eAAe,UAAS,qBAAA;IACzC,WAAW,QAAA,eAAe,UAAS,0BAAA;IACnC,cAAc,QAAA;IACd,WAAW,QAAA;IACX,sBAAkB;IAClB,qBAAiB;IACjB,sBAAgB,OAAA,OAAA,OAAA,MAAG,UAAU,QAAA,oBAAoB,MAAK;IACtD,sBAAkB"}

@@ -56,3 +56,4 @@ import IconSelector_default from "../../../components/IconSelector.vue.js";

telemetry: { type: Boolean },
onUpdateTelemetry: { type: Function }
onUpdateTelemetry: { type: Function },
options: {}
},

@@ -59,0 +60,0 @@ setup(__props) {

@@ -1,1 +0,1 @@

{"version":3,"file":"DocumentCollection.vue.script.js","names":[],"sources":["../../../../src/v2/features/collection/DocumentCollection.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Document Collection Page\n *\n * Displays primary document editing and viewing interface, enabling users to:\n * - Choose a document icon\n * - Edit the document title\n * - Navigate among Overview, Servers, Authentication, Environment, Cookies, and Settings tabs\n */\nexport default {\n name: 'DocumentCollection',\n}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarModal,\n ScalarSavePrompt,\n useLoadingState,\n useModal,\n} from '@scalar/components'\nimport {\n ScalarIconCloudArrowDown,\n ScalarIconDownload,\n ScalarIconFloppyDisk,\n ScalarIconSpinner,\n ScalarIconWarning,\n} from '@scalar/icons'\nimport { LibraryIcon } from '@scalar/icons/library'\nimport { apply, type Difference, type merge } from '@scalar/json-magic/diff'\nimport { useToasts } from '@scalar/use-toasts'\nimport { deepClone } from '@scalar/workspace-store/helpers/deep-clone'\nimport { computed, ref } from 'vue'\nimport { RouterView } from 'vue-router'\n\nimport IconSelector from '@/components/IconSelector.vue'\nimport type { RouteProps } from '@/v2/features/app/helpers/routes'\nimport { downloadAsFile } from '@/v2/helpers/download-document'\n\nimport LabelInput from './components/LabelInput.vue'\nimport SyncConflictResolutionEditor from './components/SyncConflictResolutionEditor.vue'\nimport Tabs from './components/Tabs.vue'\n\nconst props = defineProps<RouteProps>()\n\n/** Snag the title from the info object */\nconst title = computed(() => props.document?.info?.title ?? '')\n\n/** Default to the folder icon */\nconst icon = computed(\n () => props.document?.['x-scalar-icon'] || 'interface-content-folder',\n)\n\nconst syncModal = useModal()\nconst dirtyBeforeSyncModal = useModal()\n\nconst isDocumentDirty = computed(\n () => props.document?.['x-scalar-is-dirty'] === true,\n)\n\nconst saveLoader = useLoadingState()\n\nconst documentSourceUrl = computed(\n () => props.document?.['x-scalar-original-source-url'] as string | undefined,\n)\n\nconst documentRegistryMeta = computed(\n () =>\n props.document?.['x-scalar-registry-meta'] as\n | { namespace: string; slug: string }\n | undefined,\n)\n\n/** Show Sync when the document has a source URL or registry meta (registry can be used if fetchRegistryDocument is set). */\nconst canShowSyncButton = computed(\n () =>\n documentSourceUrl.value !== undefined ||\n documentRegistryMeta.value !== undefined,\n)\n\nconst { toast } = useToasts()\n\nconst undoChanges = () => {\n props.workspaceStore.revertDocumentChanges(props.documentSlug)\n}\n\nconst saveChanges = async () => {\n saveLoader.start()\n const res = await props.workspaceStore.saveDocument(props.documentSlug)\n await (res ? saveLoader.validate() : saveLoader.invalidate({ persist: true }))\n}\n\n/** Downloads the document as a JSON file using the last saved state. */\nconst downloadDocument = () => {\n const content = props.workspaceStore.exportDocument(\n props.documentSlug,\n 'json',\n false,\n )\n if (!content) return\n const baseName = title.value.replace(/[^\\w\\s-]/g, '').trim() || 'document'\n downloadAsFile(content, `${baseName}.json`)\n}\n\nconst handleSaveThenCloseDirtyModal = async () => {\n await props.workspaceStore.saveDocument(props.documentSlug)\n dirtyBeforeSyncModal.hide()\n await handleSyncFlow()\n}\n\nconst handleDiscardThenCloseDirtyModal = async () => {\n await props.workspaceStore.revertDocumentChanges(props.documentSlug)\n dirtyBeforeSyncModal.hide()\n await handleSyncFlow()\n}\n\nconst isSyncInProgress = ref(false)\n\nconst rebaseResult = ref<{\n originalDocument: Record<string, unknown>\n resolvedDocument: Record<string, unknown>\n conflicts: ReturnType<typeof merge>['conflicts']\n applyChanges: (\n applyChangesInput:\n | {\n resolvedConflicts: Difference<unknown>[]\n }\n | {\n resolvedDocument: Record<string, unknown>\n },\n ) => Promise<void>\n} | null>(null)\n\n/**\n * Resolves the source for syncing. Registry meta has priority over x-scalar-original-source-url\n * when fetchRegistryDocument is provided. Returns either a URL or the full document object.\n */\nconst resolveSyncInput = async (): Promise<\n { url: string } | { document: Record<string, unknown> } | null\n> => {\n const registryMeta = documentRegistryMeta.value\n if (registryMeta && props.fetchRegistryDocument) {\n try {\n const result = await props.fetchRegistryDocument(registryMeta)\n if (!result.ok) {\n toast(result.error, 'error')\n return null\n }\n return { document: result.data }\n } catch (err) {\n toast('Failed to resolve document from registry', 'error')\n return null\n }\n }\n const url = documentSourceUrl.value\n if (url) {\n return { url }\n }\n return null\n}\n\n/**\n * Handles actions to perform when synchronization is complete.\n * Hides the sync modal, resets the sync progress flag, and emits the\n * 'hooks:on:rebase:document:complete' event with document metadata.\n */\nconst onSyncComplete = () => {\n syncModal.hide()\n isSyncInProgress.value = false\n // Display the toast to show that the sync is complete\n toast(\n 'Your document has been rebased with the latest version from the source.',\n 'info',\n )\n // Emit the event to notify other components that the sync is complete\n props.eventBus.emit('hooks:on:rebase:document:complete', {\n meta: {\n documentName: props.documentSlug,\n },\n })\n}\n\n/**\n * Handles errors that occur during synchronization.\n * If an error string is provided, it displays the error via toast.\n * Always resets the sync progress flag.\n */\nconst onSyncError = (error: string | null) => {\n if (error !== null) {\n toast(error, 'error')\n }\n isSyncInProgress.value = false\n}\n\n/**\n * Handles the synchronization flow for a document.\n * Checks for unsaved changes, resolves source (registry over URL),\n * initiates rebasing, handles conflicts, and emits completion events.\n * If conflicts are detected, a modal dialog is shown for user resolution.\n */\nconst handleSyncFlow = async () => {\n if (isDocumentDirty.value) {\n dirtyBeforeSyncModal.show()\n return\n }\n\n if (isSyncInProgress.value) {\n return\n }\n\n isSyncInProgress.value = true\n\n const input = await resolveSyncInput()\n if (!input) {\n onSyncError(null)\n return\n }\n\n const result = await props.workspaceStore.rebaseDocument({\n name: props.documentSlug,\n ...input,\n })\n\n if (result?.ok) {\n const originalDocument =\n props.workspaceStore.getOriginalDocument(props.documentSlug) ?? {}\n rebaseResult.value = {\n conflicts: result.conflicts,\n applyChanges: result.applyChanges,\n resolvedDocument: apply(deepClone(originalDocument), result.changes),\n originalDocument,\n }\n\n if (rebaseResult.value.conflicts.length > 0) {\n syncModal.show()\n } else {\n // If there is no conflict just rebase immediately\n await rebaseResult.value?.applyChanges({\n resolvedDocument: rebaseResult.value.resolvedDocument,\n })\n onSyncComplete()\n }\n } else if (result?.ok === false && result.type === 'NO_CHANGES_DETECTED') {\n // Emit the event either way even if there was no need to rebase the document\n onSyncComplete()\n } else {\n onSyncError('Failed to sync document')\n }\n}\n\n/*\n * Handles applying changes to the current document after conflict resolution.\n * Emits a completion event and hides the sync modal dialog.\n */\nconst handleApplyChanges = async ({\n resolvedDocument,\n}: {\n resolvedDocument: Record<string, unknown>\n}) => {\n await rebaseResult.value?.applyChanges({ resolvedDocument })\n props.eventBus.emit('hooks:on:rebase:document:complete', {\n meta: {\n documentName: props.documentSlug,\n },\n })\n syncModal.hide()\n}\n\n/**\n * Resets sync state when the sync conflict modal is closed (dismissed or after\n * applying changes). Ensures the Sync button is re-enabled and conflict state\n * is cleared.\n */\nconst onSyncModalClose = () => {\n isSyncInProgress.value = false\n rebaseResult.value = null\n}\n</script>\n\n<template>\n <div class=\"custom-scroll h-full\">\n <div\n v-if=\"document\"\n class=\"md:max-w-content w-full px-3 md:mx-auto\">\n <!-- Header -->\n <div\n :aria-label=\"`title: ${title}`\"\n class=\"md:max-w-content mx-auto flex h-fit w-full flex-col gap-2 pt-14 pb-3 md:pt-6\">\n <ScalarSavePrompt\n v-model=\"isDocumentDirty\"\n class=\"w-content-padded-4 max-w-full-padded-4 absolute\"\n :loader=\"saveLoader\"\n @discard=\"undoChanges\"\n @save=\"saveChanges\" />\n <div class=\"flex flex-row items-center justify-between gap-2\">\n <div class=\"flex min-w-0 items-center gap-2\">\n <IconSelector\n :modelValue=\"icon\"\n placement=\"bottom-start\"\n @update:modelValue=\"\n (icon) => eventBus.emit('document:update:icon', icon)\n \">\n <ScalarButton\n class=\"hover:bg-b-2 aspect-square h-7 w-7 cursor-pointer rounded border border-transparent p-0 hover:border-inherit\"\n variant=\"ghost\">\n <LibraryIcon\n class=\"text-c-2 size-5\"\n :src=\"icon\"\n stroke-width=\"2\" />\n </ScalarButton>\n </IconSelector>\n\n <div class=\"group relative ml-1.25 min-w-0\">\n <LabelInput\n class=\"text-xl font-bold\"\n inputId=\"documentName\"\n :modelValue=\"title\"\n @update:modelValue=\"\n (title) => eventBus.emit('document:update:info', { title })\n \" />\n </div>\n </div>\n\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex shrink-0 items-center gap-2\"\n size=\"xs\"\n type=\"button\"\n variant=\"ghost\"\n @click=\"downloadDocument\">\n <ScalarIconDownload\n size=\"sm\"\n thickness=\"1.5\" />\n <span>Download document</span>\n </ScalarButton>\n\n <ScalarButton\n v-if=\"canShowSyncButton\"\n class=\"text-c-2 hover:text-c-1 shrink-0 gap-1.5\"\n data-testid=\"document-sync-button\"\n :disabled=\"isSyncInProgress\"\n size=\"xs\"\n :title=\"'Pull the latest version from the document source and merge with your local copy. Save your changes first if you have unsaved edits.'\"\n type=\"button\"\n variant=\"ghost\"\n @click=\"handleSyncFlow\">\n <ScalarIconSpinner\n v-if=\"isSyncInProgress\"\n class=\"size-3.5 animate-spin\"\n size=\"sm\" />\n <ScalarIconCloudArrowDown\n v-else\n class=\"size-3.5\"\n size=\"sm\"\n thickness=\"1.5\" />\n <span>Sync from source</span>\n </ScalarButton>\n </div>\n </div>\n\n <!-- Tabs -->\n <Tabs type=\"document\" />\n\n <!-- Router views -->\n <div class=\"px-1.5 pt-8 pb-20\">\n <RouterView v-slot=\"{ Component }\">\n <component\n :is=\"Component\"\n v-bind=\"props\"\n collectionType=\"document\" />\n </RouterView>\n </div>\n </div>\n\n <!-- Document not found -->\n <div\n v-else\n class=\"flex w-full flex-1 items-center justify-center\">\n <div class=\"flex h-full flex-col items-center justify-center\">\n <h1 class=\"text-2xl font-bold\">Document not found</h1>\n <p class=\"text-gray-500\">\n The document you are looking for does not exist.\n </p>\n </div>\n </div>\n </div>\n <ScalarModal\n bodyClass=\"border-t-0 rounded-t-lg flex flex-col gap-5\"\n size=\"xs\"\n :state=\"dirtyBeforeSyncModal\"\n title=\"Sync requires saved document\"\n @close=\"dirtyBeforeSyncModal.hide()\">\n <div class=\"flex flex-col gap-5\">\n <div class=\"flex gap-3\">\n <div\n aria-hidden=\"true\"\n class=\"bg-b-3 text-c-2 flex size-10 shrink-0 items-center justify-center rounded-lg\">\n <ScalarIconWarning class=\"text-yellow size-5\" />\n </div>\n <div class=\"min-w-0 flex-1 space-y-1\">\n <p class=\"text-c-1 text-sm leading-snug font-medium\">\n You have unsaved changes\n </p>\n <p class=\"text-c-2 text-sm leading-relaxed\">\n Save your work to keep changes, or discard to revert to the last\n saved version. Then you can sync with the source.\n </p>\n </div>\n </div>\n <div class=\"flex flex-wrap items-center justify-end gap-2 border-t pt-4\">\n <ScalarButton\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n @click=\"dirtyBeforeSyncModal.hide()\">\n Cancel\n </ScalarButton>\n <ScalarButton\n size=\"sm\"\n type=\"button\"\n variant=\"outlined\"\n @click=\"handleDiscardThenCloseDirtyModal\">\n Discard changes\n </ScalarButton>\n <ScalarButton\n class=\"flex items-center gap-2\"\n size=\"sm\"\n type=\"button\"\n variant=\"solid\"\n @click=\"handleSaveThenCloseDirtyModal\">\n <ScalarIconFloppyDisk\n size=\"sm\"\n thickness=\"1.5\" />\n Save and continue\n </ScalarButton>\n </div>\n </div>\n </ScalarModal>\n <ScalarModal\n v-if=\"rebaseResult\"\n bodyClass=\"sync-conflict-modal-root flex h-dvh flex-col p-4\"\n maxWidth=\"calc(100dvw - 32px)\"\n size=\"full\"\n :state=\"syncModal\"\n @close=\"onSyncModalClose\">\n <div class=\"flex h-full w-full flex-col gap-4 overflow-hidden\">\n <SyncConflictResolutionEditor\n :baseDocument=\"rebaseResult.originalDocument\"\n :conflicts=\"rebaseResult.conflicts\"\n :resolvedDocument=\"rebaseResult.resolvedDocument\"\n @applyChanges=\"(payload) => handleApplyChanges(payload)\" />\n </div>\n </ScalarModal>\n</template>\n\n<style>\n.full-size-styles:has(.sync-conflict-modal-root) {\n width: 100dvw !important;\n max-width: 100dvw !important;\n border-right: none !important;\n}\n\n.full-size-styles:has(.sync-conflict-modal-root)::after {\n display: none;\n}\n</style>\n"],"mappings":"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"}
{"version":3,"file":"DocumentCollection.vue.script.js","names":[],"sources":["../../../../src/v2/features/collection/DocumentCollection.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Document Collection Page\n *\n * Displays primary document editing and viewing interface, enabling users to:\n * - Choose a document icon\n * - Edit the document title\n * - Navigate among Overview, Servers, Authentication, Environment, Cookies, and Settings tabs\n */\nexport default {\n name: 'DocumentCollection',\n}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarModal,\n ScalarSavePrompt,\n useLoadingState,\n useModal,\n} from '@scalar/components'\nimport {\n ScalarIconCloudArrowDown,\n ScalarIconDownload,\n ScalarIconFloppyDisk,\n ScalarIconSpinner,\n ScalarIconWarning,\n} from '@scalar/icons'\nimport { LibraryIcon } from '@scalar/icons/library'\nimport { apply, type Difference, type merge } from '@scalar/json-magic/diff'\nimport { useToasts } from '@scalar/use-toasts'\nimport { deepClone } from '@scalar/workspace-store/helpers/deep-clone'\nimport { computed, ref } from 'vue'\nimport { RouterView } from 'vue-router'\n\nimport IconSelector from '@/components/IconSelector.vue'\nimport type { RouteProps } from '@/v2/features/app/helpers/routes'\nimport { downloadAsFile } from '@/v2/helpers/download-document'\n\nimport LabelInput from './components/LabelInput.vue'\nimport SyncConflictResolutionEditor from './components/SyncConflictResolutionEditor.vue'\nimport Tabs from './components/Tabs.vue'\n\nconst props = defineProps<RouteProps>()\n\n/** Snag the title from the info object */\nconst title = computed(() => props.document?.info?.title ?? '')\n\n/** Default to the folder icon */\nconst icon = computed(\n () => props.document?.['x-scalar-icon'] || 'interface-content-folder',\n)\n\nconst syncModal = useModal()\nconst dirtyBeforeSyncModal = useModal()\n\nconst isDocumentDirty = computed(\n () => props.document?.['x-scalar-is-dirty'] === true,\n)\n\nconst saveLoader = useLoadingState()\n\nconst documentSourceUrl = computed(\n () => props.document?.['x-scalar-original-source-url'] as string | undefined,\n)\n\nconst documentRegistryMeta = computed(\n () =>\n props.document?.['x-scalar-registry-meta'] as\n | { namespace: string; slug: string }\n | undefined,\n)\n\n/** Show Sync when the document has a source URL or registry meta (registry can be used if fetchRegistryDocument is set). */\nconst canShowSyncButton = computed(\n () =>\n documentSourceUrl.value !== undefined ||\n documentRegistryMeta.value !== undefined,\n)\n\nconst { toast } = useToasts()\n\nconst undoChanges = () => {\n props.workspaceStore.revertDocumentChanges(props.documentSlug)\n}\n\nconst saveChanges = async () => {\n saveLoader.start()\n const res = await props.workspaceStore.saveDocument(props.documentSlug)\n await (res ? saveLoader.validate() : saveLoader.invalidate({ persist: true }))\n}\n\n/** Downloads the document as a JSON file using the last saved state. */\nconst downloadDocument = () => {\n const content = props.workspaceStore.exportDocument(\n props.documentSlug,\n 'json',\n false,\n )\n if (!content) return\n const baseName = title.value.replace(/[^\\w\\s-]/g, '').trim() || 'document'\n downloadAsFile(content, `${baseName}.json`)\n}\n\nconst handleSaveThenCloseDirtyModal = async () => {\n await props.workspaceStore.saveDocument(props.documentSlug)\n dirtyBeforeSyncModal.hide()\n await handleSyncFlow()\n}\n\nconst handleDiscardThenCloseDirtyModal = async () => {\n await props.workspaceStore.revertDocumentChanges(props.documentSlug)\n dirtyBeforeSyncModal.hide()\n await handleSyncFlow()\n}\n\nconst isSyncInProgress = ref(false)\n\nconst rebaseResult = ref<{\n originalDocument: Record<string, unknown>\n resolvedDocument: Record<string, unknown>\n conflicts: ReturnType<typeof merge>['conflicts']\n applyChanges: (\n applyChangesInput:\n | {\n resolvedConflicts: Difference<unknown>[]\n }\n | {\n resolvedDocument: Record<string, unknown>\n },\n ) => Promise<void>\n} | null>(null)\n\n/**\n * Resolves the source for syncing. Registry meta has priority over x-scalar-original-source-url\n * when fetchRegistryDocument is provided. Returns either a URL or the full document object.\n */\nconst resolveSyncInput = async (): Promise<\n { url: string } | { document: Record<string, unknown> } | null\n> => {\n const registryMeta = documentRegistryMeta.value\n if (registryMeta && props.fetchRegistryDocument) {\n try {\n const result = await props.fetchRegistryDocument(registryMeta)\n if (!result.ok) {\n toast(result.error, 'error')\n return null\n }\n return { document: result.data }\n } catch (err) {\n toast('Failed to resolve document from registry', 'error')\n return null\n }\n }\n const url = documentSourceUrl.value\n if (url) {\n return { url }\n }\n return null\n}\n\n/**\n * Handles actions to perform when synchronization is complete.\n * Hides the sync modal, resets the sync progress flag, and emits the\n * 'hooks:on:rebase:document:complete' event with document metadata.\n */\nconst onSyncComplete = () => {\n syncModal.hide()\n isSyncInProgress.value = false\n // Display the toast to show that the sync is complete\n toast(\n 'Your document has been rebased with the latest version from the source.',\n 'info',\n )\n // Emit the event to notify other components that the sync is complete\n props.eventBus.emit('hooks:on:rebase:document:complete', {\n meta: {\n documentName: props.documentSlug,\n },\n })\n}\n\n/**\n * Handles errors that occur during synchronization.\n * If an error string is provided, it displays the error via toast.\n * Always resets the sync progress flag.\n */\nconst onSyncError = (error: string | null) => {\n if (error !== null) {\n toast(error, 'error')\n }\n isSyncInProgress.value = false\n}\n\n/**\n * Handles the synchronization flow for a document.\n * Checks for unsaved changes, resolves source (registry over URL),\n * initiates rebasing, handles conflicts, and emits completion events.\n * If conflicts are detected, a modal dialog is shown for user resolution.\n */\nconst handleSyncFlow = async () => {\n if (isDocumentDirty.value) {\n dirtyBeforeSyncModal.show()\n return\n }\n\n if (isSyncInProgress.value) {\n return\n }\n\n isSyncInProgress.value = true\n\n const input = await resolveSyncInput()\n if (!input) {\n onSyncError(null)\n return\n }\n\n const result = await props.workspaceStore.rebaseDocument({\n name: props.documentSlug,\n ...input,\n })\n\n if (result?.ok) {\n const originalDocument =\n props.workspaceStore.getOriginalDocument(props.documentSlug) ?? {}\n rebaseResult.value = {\n conflicts: result.conflicts,\n applyChanges: result.applyChanges,\n resolvedDocument: apply(deepClone(originalDocument), result.changes),\n originalDocument,\n }\n\n if (rebaseResult.value.conflicts.length > 0) {\n syncModal.show()\n } else {\n // If there is no conflict just rebase immediately\n await rebaseResult.value?.applyChanges({\n resolvedDocument: rebaseResult.value.resolvedDocument,\n })\n onSyncComplete()\n }\n } else if (result?.ok === false && result.type === 'NO_CHANGES_DETECTED') {\n // Emit the event either way even if there was no need to rebase the document\n onSyncComplete()\n } else {\n onSyncError('Failed to sync document')\n }\n}\n\n/*\n * Handles applying changes to the current document after conflict resolution.\n * Emits a completion event and hides the sync modal dialog.\n */\nconst handleApplyChanges = async ({\n resolvedDocument,\n}: {\n resolvedDocument: Record<string, unknown>\n}) => {\n await rebaseResult.value?.applyChanges({ resolvedDocument })\n props.eventBus.emit('hooks:on:rebase:document:complete', {\n meta: {\n documentName: props.documentSlug,\n },\n })\n syncModal.hide()\n}\n\n/**\n * Resets sync state when the sync conflict modal is closed (dismissed or after\n * applying changes). Ensures the Sync button is re-enabled and conflict state\n * is cleared.\n */\nconst onSyncModalClose = () => {\n isSyncInProgress.value = false\n rebaseResult.value = null\n}\n</script>\n\n<template>\n <div class=\"custom-scroll h-full\">\n <div\n v-if=\"document\"\n class=\"md:max-w-content w-full px-3 md:mx-auto\">\n <!-- Header -->\n <div\n :aria-label=\"`title: ${title}`\"\n class=\"md:max-w-content mx-auto flex h-fit w-full flex-col gap-2 pt-14 pb-3 md:pt-6\">\n <ScalarSavePrompt\n v-model=\"isDocumentDirty\"\n class=\"w-content-padded-4 max-w-full-padded-4 absolute\"\n :loader=\"saveLoader\"\n @discard=\"undoChanges\"\n @save=\"saveChanges\" />\n <div class=\"flex flex-row items-center justify-between gap-2\">\n <div class=\"flex min-w-0 items-center gap-2\">\n <IconSelector\n :modelValue=\"icon\"\n placement=\"bottom-start\"\n @update:modelValue=\"\n (icon) => eventBus.emit('document:update:icon', icon)\n \">\n <ScalarButton\n class=\"hover:bg-b-2 aspect-square h-7 w-7 cursor-pointer rounded border border-transparent p-0 hover:border-inherit\"\n variant=\"ghost\">\n <LibraryIcon\n class=\"text-c-2 size-5\"\n :src=\"icon\"\n stroke-width=\"2\" />\n </ScalarButton>\n </IconSelector>\n\n <div class=\"group relative ml-1.25 min-w-0\">\n <LabelInput\n class=\"text-xl font-bold\"\n inputId=\"documentName\"\n :modelValue=\"title\"\n @update:modelValue=\"\n (title) => eventBus.emit('document:update:info', { title })\n \" />\n </div>\n </div>\n\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex shrink-0 items-center gap-2\"\n size=\"xs\"\n type=\"button\"\n variant=\"ghost\"\n @click=\"downloadDocument\">\n <ScalarIconDownload\n size=\"sm\"\n thickness=\"1.5\" />\n <span>Download document</span>\n </ScalarButton>\n\n <ScalarButton\n v-if=\"canShowSyncButton\"\n class=\"text-c-2 hover:text-c-1 shrink-0 gap-1.5\"\n data-testid=\"document-sync-button\"\n :disabled=\"isSyncInProgress\"\n size=\"xs\"\n :title=\"'Pull the latest version from the document source and merge with your local copy. Save your changes first if you have unsaved edits.'\"\n type=\"button\"\n variant=\"ghost\"\n @click=\"handleSyncFlow\">\n <ScalarIconSpinner\n v-if=\"isSyncInProgress\"\n class=\"size-3.5 animate-spin\"\n size=\"sm\" />\n <ScalarIconCloudArrowDown\n v-else\n class=\"size-3.5\"\n size=\"sm\"\n thickness=\"1.5\" />\n <span>Sync from source</span>\n </ScalarButton>\n </div>\n </div>\n\n <!-- Tabs -->\n <Tabs type=\"document\" />\n\n <!-- Router views -->\n <div class=\"px-1.5 pt-8 pb-20\">\n <RouterView v-slot=\"{ Component }\">\n <component\n :is=\"Component\"\n v-bind=\"props\"\n collectionType=\"document\" />\n </RouterView>\n </div>\n </div>\n\n <!-- Document not found -->\n <div\n v-else\n class=\"flex w-full flex-1 items-center justify-center\">\n <div class=\"flex h-full flex-col items-center justify-center\">\n <h1 class=\"text-2xl font-bold\">Document not found</h1>\n <p class=\"text-gray-500\">\n The document you are looking for does not exist.\n </p>\n </div>\n </div>\n </div>\n <ScalarModal\n bodyClass=\"border-t-0 rounded-t-lg flex flex-col gap-5\"\n size=\"xs\"\n :state=\"dirtyBeforeSyncModal\"\n title=\"Sync requires saved document\"\n @close=\"dirtyBeforeSyncModal.hide()\">\n <div class=\"flex flex-col gap-5\">\n <div class=\"flex gap-3\">\n <div\n aria-hidden=\"true\"\n class=\"bg-b-3 text-c-2 flex size-10 shrink-0 items-center justify-center rounded-lg\">\n <ScalarIconWarning class=\"text-yellow size-5\" />\n </div>\n <div class=\"min-w-0 flex-1 space-y-1\">\n <p class=\"text-c-1 text-sm leading-snug font-medium\">\n You have unsaved changes\n </p>\n <p class=\"text-c-2 text-sm leading-relaxed\">\n Save your work to keep changes, or discard to revert to the last\n saved version. Then you can sync with the source.\n </p>\n </div>\n </div>\n <div class=\"flex flex-wrap items-center justify-end gap-2 border-t pt-4\">\n <ScalarButton\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n @click=\"dirtyBeforeSyncModal.hide()\">\n Cancel\n </ScalarButton>\n <ScalarButton\n size=\"sm\"\n type=\"button\"\n variant=\"outlined\"\n @click=\"handleDiscardThenCloseDirtyModal\">\n Discard changes\n </ScalarButton>\n <ScalarButton\n class=\"flex items-center gap-2\"\n size=\"sm\"\n type=\"button\"\n variant=\"solid\"\n @click=\"handleSaveThenCloseDirtyModal\">\n <ScalarIconFloppyDisk\n size=\"sm\"\n thickness=\"1.5\" />\n Save and continue\n </ScalarButton>\n </div>\n </div>\n </ScalarModal>\n <ScalarModal\n v-if=\"rebaseResult\"\n bodyClass=\"sync-conflict-modal-root flex h-dvh flex-col p-4\"\n maxWidth=\"calc(100dvw - 32px)\"\n size=\"full\"\n :state=\"syncModal\"\n @close=\"onSyncModalClose\">\n <div class=\"flex h-full w-full flex-col gap-4 overflow-hidden\">\n <SyncConflictResolutionEditor\n :baseDocument=\"rebaseResult.originalDocument\"\n :conflicts=\"rebaseResult.conflicts\"\n :resolvedDocument=\"rebaseResult.resolvedDocument\"\n @applyChanges=\"(payload) => handleApplyChanges(payload)\" />\n </div>\n </ScalarModal>\n</template>\n\n<style>\n.full-size-styles:has(.sync-conflict-modal-root) {\n width: 100dvw !important;\n max-width: 100dvw !important;\n border-right: none !important;\n}\n\n.full-size-styles:has(.sync-conflict-modal-root)::after {\n display: none;\n}\n</style>\n"],"mappings":"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"}

@@ -39,3 +39,4 @@ import LabelInput_default from "./components/LabelInput.vue.js";

telemetry: { type: Boolean },
onUpdateTelemetry: { type: Function }
onUpdateTelemetry: { type: Function },
options: {}
},

@@ -42,0 +43,0 @@ setup(__props) {

@@ -1,1 +0,1 @@

{"version":3,"file":"OperationCollection.vue.script.js","names":[],"sources":["../../../../src/v2/features/collection/OperationCollection.vue"],"sourcesContent":["<script lang=\"ts\">\n/** Document collection page — tabs for Overview, Servers, Auth, Environment, Cookies, and Settings. */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { computed, ref, watch } from 'vue'\nimport { RouterView } from 'vue-router'\n\nimport type { RouteProps } from '@/v2/features/app/helpers/routes'\nimport LabelInput from '@/v2/features/collection/components/LabelInput.vue'\n\nimport Tabs from './components/Tabs.vue'\n\nconst props = defineProps<RouteProps>()\n\nconst operation = computed(() => {\n if (!props.path || !props.method) {\n return undefined\n }\n\n return getResolvedRef(props.document?.paths?.[props.path]?.[props.method])\n})\n\n/**\n * Local copy of the label so we can reset on empty-blur rejection and stay in\n * sync when Vue Router reuses this component across workspace navigations.\n */\nconst operationSummary = ref(operation.value?.summary ?? '')\n\nwatch(\n () => operation.value?.summary,\n (newSummary) => {\n operationSummary.value = newSummary ?? ''\n },\n)\n\n/** Emits the rename event on blur, or resets the input if the title is blank. */\nconst handleSummaryUpdate = (payload: string) => {\n const { path, method } = props\n\n if (!path || !method || !isHttpMethod(method)) {\n return\n }\n\n props.eventBus.emit('operation:update:meta', {\n meta: { path, method },\n payload: {\n summary: payload.trim(),\n },\n })\n}\n\nconst operationPlaceholder = computed(() => {\n if (!props.path || !props.method) {\n return 'Untitled Operation'\n }\n return `${props.method.toUpperCase()} ${props.path}`\n})\n</script>\n\n<template>\n <div\n v-if=\"operation !== undefined\"\n class=\"custom-scroll h-full\">\n <div class=\"w-full px-3 md:mx-auto md:max-w-180\">\n <!-- Header -->\n <div\n :aria-label=\"`title: ${operationSummary}`\"\n class=\"mx-auto flex h-fit w-full flex-row items-center gap-2 pt-14 pb-3 md:max-w-180 md:pt-8\">\n <div class=\"group relative ml-1.25\">\n <LabelInput\n v-model=\"operationSummary\"\n class=\"text-xl font-bold\"\n inputId=\"operationSummary\"\n :placeholder=\"operationPlaceholder\"\n @blur=\"handleSummaryUpdate\" />\n </div>\n </div>\n\n <!-- Tabs -->\n <Tabs type=\"operation\" />\n\n <!-- Router views -->\n <div class=\"px-1.5 py-8\">\n <RouterView\n v-bind=\"props\"\n collectionType=\"operation\" />\n </div>\n </div>\n </div>\n\n <!-- Operation not found -->\n <div\n v-else\n class=\"flex w-full flex-1 items-center justify-center\">\n <div class=\"flex h-full flex-col items-center justify-center\">\n <h1 class=\"text-2xl font-bold\">Operation not found</h1>\n <p class=\"text-gray-500\">\n The operation you are looking for does not exist.\n </p>\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgBA,MAAM,QAAQ;EAEd,MAAM,YAAY,eAAe;AAC/B,OAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,OACxB;AAGF,UAAO,eAAe,MAAM,UAAU,QAAQ,MAAM,QAAQ,MAAM,QAAO;IAC1E;;;;;EAMD,MAAM,mBAAmB,IAAI,UAAU,OAAO,WAAW,GAAE;AAE3D,cACQ,UAAU,OAAO,UACtB,eAAe;AACd,oBAAiB,QAAQ,cAAc;IAE3C;;EAGA,MAAM,uBAAuB,YAAoB;GAC/C,MAAM,EAAE,MAAM,WAAW;AAEzB,OAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,aAAa,OAAO,CAC3C;AAGF,SAAM,SAAS,KAAK,yBAAyB;IAC3C,MAAM;KAAE;KAAM;KAAQ;IACtB,SAAS,EACP,SAAS,QAAQ,MAAM,EACxB;IACF,CAAA;;EAGH,MAAM,uBAAuB,eAAe;AAC1C,OAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,OACxB,QAAO;AAET,UAAO,GAAG,MAAM,OAAO,aAAa,CAAC,GAAG,MAAM;IAC/C;;UAKS,UAAA,UAAc,KAAA,KAAA,WAAA,EADtB,mBA4BM,OA5BN,YA4BM,CAzBJ,mBAwBM,OAxBN,YAwBM;IAtBJ,mBAWM,OAAA;KAVH,cAAU,UAAY,iBAAA;KACvB,OAAM;QACN,mBAOM,OAPN,YAOM,CANJ,YAKgC,oBAAA;iBAJrB,iBAAA;mFAAgB,QAAA;KACzB,OAAM;KACN,SAAQ;KACP,aAAa,qBAAA;KACb,QAAM;;IAKb,YAAyB,cAAA,EAAnB,MAAK,aAAW,CAAA;IAGtB,mBAIM,OAJN,YAIM,CAHJ,YAE+B,MAAA,WAAA,EAF/B,WACU,OAAK,EACb,gBAAe,aAAW,CAAA,EAAA,MAAA,GAAA,CAAA,CAAA;yBAMlC,mBASM,OATN,YASM,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CANJ,mBAKM,OAAA,EALD,OAAM,oDAAkD,EAAA,CAC3D,mBAAuD,MAAA,EAAnD,OAAM,sBAAoB,EAAC,sBAAmB,EAClD,mBAEI,KAAA,EAFD,OAAM,iBAAe,EAAC,sDAEzB,CAAA,EAAA,GAAA,CAAA,EAAA,CAAA"}
{"version":3,"file":"OperationCollection.vue.script.js","names":[],"sources":["../../../../src/v2/features/collection/OperationCollection.vue"],"sourcesContent":["<script lang=\"ts\">\n/** Document collection page — tabs for Overview, Servers, Auth, Environment, Cookies, and Settings. */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { computed, ref, watch } from 'vue'\nimport { RouterView } from 'vue-router'\n\nimport type { RouteProps } from '@/v2/features/app/helpers/routes'\nimport LabelInput from '@/v2/features/collection/components/LabelInput.vue'\n\nimport Tabs from './components/Tabs.vue'\n\nconst props = defineProps<RouteProps>()\n\nconst operation = computed(() => {\n if (!props.path || !props.method) {\n return undefined\n }\n\n return getResolvedRef(props.document?.paths?.[props.path]?.[props.method])\n})\n\n/**\n * Local copy of the label so we can reset on empty-blur rejection and stay in\n * sync when Vue Router reuses this component across workspace navigations.\n */\nconst operationSummary = ref(operation.value?.summary ?? '')\n\nwatch(\n () => operation.value?.summary,\n (newSummary) => {\n operationSummary.value = newSummary ?? ''\n },\n)\n\n/** Emits the rename event on blur, or resets the input if the title is blank. */\nconst handleSummaryUpdate = (payload: string) => {\n const { path, method } = props\n\n if (!path || !method || !isHttpMethod(method)) {\n return\n }\n\n props.eventBus.emit('operation:update:meta', {\n meta: { path, method },\n payload: {\n summary: payload.trim(),\n },\n })\n}\n\nconst operationPlaceholder = computed(() => {\n if (!props.path || !props.method) {\n return 'Untitled Operation'\n }\n return `${props.method.toUpperCase()} ${props.path}`\n})\n</script>\n\n<template>\n <div\n v-if=\"operation !== undefined\"\n class=\"custom-scroll h-full\">\n <div class=\"w-full px-3 md:mx-auto md:max-w-180\">\n <!-- Header -->\n <div\n :aria-label=\"`title: ${operationSummary}`\"\n class=\"mx-auto flex h-fit w-full flex-row items-center gap-2 pt-14 pb-3 md:max-w-180 md:pt-8\">\n <div class=\"group relative ml-1.25\">\n <LabelInput\n v-model=\"operationSummary\"\n class=\"text-xl font-bold\"\n inputId=\"operationSummary\"\n :placeholder=\"operationPlaceholder\"\n @blur=\"handleSummaryUpdate\" />\n </div>\n </div>\n\n <!-- Tabs -->\n <Tabs type=\"operation\" />\n\n <!-- Router views -->\n <div class=\"px-1.5 py-8\">\n <RouterView\n v-bind=\"props\"\n collectionType=\"operation\" />\n </div>\n </div>\n </div>\n\n <!-- Operation not found -->\n <div\n v-else\n class=\"flex w-full flex-1 items-center justify-center\">\n <div class=\"flex h-full flex-col items-center justify-center\">\n <h1 class=\"text-2xl font-bold\">Operation not found</h1>\n <p class=\"text-gray-500\">\n The operation you are looking for does not exist.\n </p>\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgBA,MAAM,QAAQ;EAEd,MAAM,YAAY,eAAe;AAC/B,OAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,OACxB;AAGF,UAAO,eAAe,MAAM,UAAU,QAAQ,MAAM,QAAQ,MAAM,QAAO;IAC1E;;;;;EAMD,MAAM,mBAAmB,IAAI,UAAU,OAAO,WAAW,GAAE;AAE3D,cACQ,UAAU,OAAO,UACtB,eAAe;AACd,oBAAiB,QAAQ,cAAc;IAE3C;;EAGA,MAAM,uBAAuB,YAAoB;GAC/C,MAAM,EAAE,MAAM,WAAW;AAEzB,OAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,aAAa,OAAO,CAC3C;AAGF,SAAM,SAAS,KAAK,yBAAyB;IAC3C,MAAM;KAAE;KAAM;KAAQ;IACtB,SAAS,EACP,SAAS,QAAQ,MAAM,EACxB;IACF,CAAA;;EAGH,MAAM,uBAAuB,eAAe;AAC1C,OAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,OACxB,QAAO;AAET,UAAO,GAAG,MAAM,OAAO,aAAa,CAAC,GAAG,MAAM;IAC/C;;UAKS,UAAA,UAAc,KAAA,KAAA,WAAA,EADtB,mBA4BM,OA5BN,YA4BM,CAzBJ,mBAwBM,OAxBN,YAwBM;IAtBJ,mBAWM,OAAA;KAVH,cAAU,UAAY,iBAAA;KACvB,OAAM;QACN,mBAOM,OAPN,YAOM,CANJ,YAKgC,oBAAA;iBAJrB,iBAAA;mFAAgB,QAAA;KACzB,OAAM;KACN,SAAQ;KACP,aAAa,qBAAA;KACb,QAAM;;IAKb,YAAyB,cAAA,EAAnB,MAAK,aAAW,CAAA;IAGtB,mBAIM,OAJN,YAIM,CAHJ,YAE+B,MAAA,WAAA,EAF/B,WACU,OAAK,EACb,gBAAe,aAAW,CAAA,EAAA,MAAA,GAAA,CAAA,CAAA;yBAMlC,mBASM,OATN,YASM,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CANJ,mBAKM,OAAA,EALD,OAAM,oDAAkD,EAAA,CAC3D,mBAAuD,MAAA,EAAnD,OAAM,sBAAoB,EAAC,sBAAmB,EAClD,mBAEI,KAAA,EAFD,OAAM,iBAAe,EAAC,sDAEzB,CAAA,EAAA,GAAA,CAAA,EAAA,CAAA"}

@@ -30,3 +30,4 @@ import LabelInput_default from "./components/LabelInput.vue.js";

telemetry: { type: Boolean },
onUpdateTelemetry: { type: Function }
onUpdateTelemetry: { type: Function },
options: {}
},

@@ -33,0 +34,0 @@ setup(__props) {

@@ -1,1 +0,1 @@

{"version":3,"file":"WorkspaceCollection.vue.script.js","names":[],"sources":["../../../../src/v2/features/collection/WorkspaceCollection.vue"],"sourcesContent":["<script lang=\"ts\">\n/** Document collection page — tabs for Overview, Servers, Auth, Environment, Cookies, and Settings. */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { ref, watch } from 'vue'\nimport { RouterView } from 'vue-router'\n\nimport type { RouteProps } from '@/v2/features/app/helpers/routes'\nimport LabelInput from '@/v2/features/collection/components/LabelInput.vue'\n\nimport Tabs from './components/Tabs.vue'\n\nconst props = defineProps<RouteProps>()\n\n/**\n * Local copy of the label so we can reset on empty-blur rejection and stay in\n * sync when Vue Router reuses this component across workspace navigations.\n */\nconst workspaceTitle = ref(props.activeWorkspace.label)\n\nwatch(\n () => props.activeWorkspace.label,\n (newLabel) => {\n workspaceTitle.value = newLabel\n },\n)\n\n/** Emits the rename event on blur, or resets the input if the title is blank. */\nconst handleUpdateWorkspaceTitle = (title: string) => {\n if (title.trim() === '') {\n // Force defineModel inside LabelInput to re-sync to the original value.\n workspaceTitle.value = props.activeWorkspace.label\n return\n }\n props.eventBus.emit('workspace:update:name', title)\n}\n</script>\n\n<template>\n <div class=\"custom-scroll h-full\">\n <div class=\"w-full px-3 md:mx-auto md:max-w-180\">\n <!-- Header -->\n <div\n :aria-label=\"`title: ${activeWorkspace.label}`\"\n class=\"mx-auto flex h-fit w-full flex-row items-center gap-2 pt-14 pb-3 md:max-w-180 md:pt-6\">\n <div class=\"group relative ml-1.25\">\n <LabelInput\n v-model=\"workspaceTitle\"\n class=\"text-xl font-bold\"\n inputId=\"workspaceName\"\n placeholder=\"Untitled Workspace\"\n @blur=\"handleUpdateWorkspaceTitle\" />\n </div>\n </div>\n\n <!-- Tabs -->\n <Tabs type=\"workspace\" />\n\n <!-- Router views -->\n <div class=\"px-1.5 py-8\">\n <RouterView\n v-bind=\"props\"\n collectionType=\"workspace\" />\n </div>\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAcA,MAAM,QAAQ;;;;;EAMd,MAAM,iBAAiB,IAAI,MAAM,gBAAgB,MAAK;AAEtD,cACQ,MAAM,gBAAgB,QAC3B,aAAa;AACZ,kBAAe,QAAQ;IAE3B;;EAGA,MAAM,8BAA8B,UAAkB;AACpD,OAAI,MAAM,MAAM,KAAK,IAAI;AAEvB,mBAAe,QAAQ,MAAM,gBAAgB;AAC7C;;AAEF,SAAM,SAAS,KAAK,yBAAyB,MAAK;;;uBAKlD,mBA0BM,OA1BN,YA0BM,CAzBJ,mBAwBM,OAxBN,YAwBM;IAtBJ,mBAWM,OAAA;KAVH,cAAU,UAAY,QAAA,gBAAgB;KACvC,OAAM;QACN,mBAOM,OAPN,YAOM,CANJ,YAKuC,oBAAA;iBAJ5B,eAAA;iFAAc,QAAA;KACvB,OAAM;KACN,SAAQ;KACR,aAAY;KACX,QAAM;;IAKb,YAAyB,cAAA,EAAnB,MAAK,aAAW,CAAA;IAGtB,mBAIM,OAJN,YAIM,CAHJ,YAE+B,MAAA,WAAA,EAF/B,WACU,OAAK,EACb,gBAAe,aAAW,CAAA,EAAA,MAAA,GAAA,CAAA,CAAA"}
{"version":3,"file":"WorkspaceCollection.vue.script.js","names":[],"sources":["../../../../src/v2/features/collection/WorkspaceCollection.vue"],"sourcesContent":["<script lang=\"ts\">\n/** Document collection page — tabs for Overview, Servers, Auth, Environment, Cookies, and Settings. */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { ref, watch } from 'vue'\nimport { RouterView } from 'vue-router'\n\nimport type { RouteProps } from '@/v2/features/app/helpers/routes'\nimport LabelInput from '@/v2/features/collection/components/LabelInput.vue'\n\nimport Tabs from './components/Tabs.vue'\n\nconst props = defineProps<RouteProps>()\n\n/**\n * Local copy of the label so we can reset on empty-blur rejection and stay in\n * sync when Vue Router reuses this component across workspace navigations.\n */\nconst workspaceTitle = ref(props.activeWorkspace.label)\n\nwatch(\n () => props.activeWorkspace.label,\n (newLabel) => {\n workspaceTitle.value = newLabel\n },\n)\n\n/** Emits the rename event on blur, or resets the input if the title is blank. */\nconst handleUpdateWorkspaceTitle = (title: string) => {\n if (title.trim() === '') {\n // Force defineModel inside LabelInput to re-sync to the original value.\n workspaceTitle.value = props.activeWorkspace.label\n return\n }\n props.eventBus.emit('workspace:update:name', title)\n}\n</script>\n\n<template>\n <div class=\"custom-scroll h-full\">\n <div class=\"w-full px-3 md:mx-auto md:max-w-180\">\n <!-- Header -->\n <div\n :aria-label=\"`title: ${activeWorkspace.label}`\"\n class=\"mx-auto flex h-fit w-full flex-row items-center gap-2 pt-14 pb-3 md:max-w-180 md:pt-6\">\n <div class=\"group relative ml-1.25\">\n <LabelInput\n v-model=\"workspaceTitle\"\n class=\"text-xl font-bold\"\n inputId=\"workspaceName\"\n placeholder=\"Untitled Workspace\"\n @blur=\"handleUpdateWorkspaceTitle\" />\n </div>\n </div>\n\n <!-- Tabs -->\n <Tabs type=\"workspace\" />\n\n <!-- Router views -->\n <div class=\"px-1.5 py-8\">\n <RouterView\n v-bind=\"props\"\n collectionType=\"workspace\" />\n </div>\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAcA,MAAM,QAAQ;;;;;EAMd,MAAM,iBAAiB,IAAI,MAAM,gBAAgB,MAAK;AAEtD,cACQ,MAAM,gBAAgB,QAC3B,aAAa;AACZ,kBAAe,QAAQ;IAE3B;;EAGA,MAAM,8BAA8B,UAAkB;AACpD,OAAI,MAAM,MAAM,KAAK,IAAI;AAEvB,mBAAe,QAAQ,MAAM,gBAAgB;AAC7C;;AAEF,SAAM,SAAS,KAAK,yBAAyB,MAAK;;;uBAKlD,mBA0BM,OA1BN,YA0BM,CAzBJ,mBAwBM,OAxBN,YAwBM;IAtBJ,mBAWM,OAAA;KAVH,cAAU,UAAY,QAAA,gBAAgB;KACvC,OAAM;QACN,mBAOM,OAPN,YAOM,CANJ,YAKuC,oBAAA;iBAJ5B,eAAA;iFAAc,QAAA;KACvB,OAAM;KACN,SAAQ;KACR,aAAY;KACX,QAAM;;IAKb,YAAyB,cAAA,EAAnB,MAAK,aAAW,CAAA;IAGtB,mBAIM,OAJN,YAIM,CAHJ,YAE+B,MAAA,WAAA,EAF/B,WACU,OAAK,EACb,gBAAe,aAAW,CAAA,EAAA,MAAA,GAAA,CAAA,CAAA"}

@@ -37,4 +37,4 @@ import { type LoadingState } from '@scalar/components';

}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
cancel: () => any;
submit: () => any;
cancel: () => any;
back: (e: KeyboardEvent) => any;

@@ -47,4 +47,4 @@ }, string, import("vue").PublicProps, Readonly<{

}> & Readonly<{
onCancel?: (() => any) | undefined;
onSubmit?: (() => any) | undefined;
onCancel?: (() => any) | undefined;
onBack?: ((e: KeyboardEvent) => any) | undefined;

@@ -51,0 +51,0 @@ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {

@@ -7,7 +7,7 @@ import { type ModalState } from '@scalar/components';

declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
cancel: () => any;
submit: () => any;
cancel: () => any;
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
onCancel?: (() => any) | undefined;
onSubmit?: (() => any) | undefined;
onCancel?: (() => any) | undefined;
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;

@@ -14,0 +14,0 @@ declare const _default: typeof __VLS_export;

import type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments';
type __VLS_Props = {
query: string;
environment: XScalarEnvironment;
environment?: XScalarEnvironment;
dropdownPosition?: {

@@ -6,0 +6,0 @@ left: number;

@@ -1,1 +0,1 @@

{"version":3,"file":"EnvironmentVariablesDropdown.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/environments/components/EnvironmentVariablesDropdown.vue"],"names":[],"mappings":"AA6PA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2EAA2E,CAAA;AASnH,KAAK,WAAW,GAAG;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,kBAAkB,CAAA;IAC/B,gBAAgB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;IAChD,iFAAiF;IACjF,oBAAoB,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAC9D,CAAC;AAqYF,QAAA,MAAM,YAAY;gCAnQiB,IAAI,GAAG,MAAM;;;;;;;;kFAuQ9C,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
{"version":3,"file":"EnvironmentVariablesDropdown.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/environments/components/EnvironmentVariablesDropdown.vue"],"names":[],"mappings":"AA6PA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2EAA2E,CAAA;AASnH,KAAK,WAAW,GAAG;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,kBAAkB,CAAA;IAChC,gBAAgB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;IAChD,iFAAiF;IACjF,oBAAoB,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAC9D,CAAC;AAqYF,QAAA,MAAM,YAAY;gCAnQiB,IAAI,GAAG,MAAM;;;;;;;;kFAuQ9C,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}

@@ -1,1 +0,1 @@

{"version":3,"file":"EnvironmentVariablesDropdown.vue.js","names":[],"sources":["../../../../../src/v2/features/environments/components/EnvironmentVariablesDropdown.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton, ScalarTeleport } from '@scalar/components'\nimport { ScalarIconPlus } from '@scalar/icons'\nimport { POPULAR_CONTEXT_FUNCTION_KEYS } from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { onClickOutside } from '@vueuse/core'\nimport Fuse from 'fuse.js'\nimport { computed, onMounted, ref, type CSSProperties } from 'vue'\n\ntype DropdownRow =\n | { kind: 'env'; key: string; secondary: string }\n | { kind: 'context'; key: string; secondary: string }\n\nconst {\n query,\n environment,\n dropdownPosition,\n contextFunctionItems = [],\n} = defineProps<{\n query: string\n environment: XScalarEnvironment\n dropdownPosition?: { left: number; top: number }\n /** Runtime placeholders such as `{{$guid}}`, shown with environment variables */\n contextFunctionItems?: { key: string; description: string }[]\n}>()\n\nconst emit = defineEmits<{\n (e: 'select', variable: string): void\n (e: 'redirect'): void\n}>()\n\nconst isOpen = ref(true)\nconst dropdownRef = ref<HTMLElement | null>(null)\nconst selectedVariableIndex = ref(0)\n\nconst redirectToEnvironment = () => {\n emit('redirect')\n isOpen.value = false\n}\n\n/** Normalize the variables to have a name and value */\nconst normalizedVariables = computed(() =>\n environment.variables.map((v) => ({\n key: v.name,\n value: typeof v.value === 'string' ? v.value : v.value.default,\n })),\n)\n\nconst contextRows = computed((): DropdownRow[] =>\n contextFunctionItems.map((item) => ({\n kind: 'context',\n key: item.key,\n secondary: item.description,\n })),\n)\n\nconst envRows = computed((): DropdownRow[] =>\n normalizedVariables.value\n .filter(({ key, value }) => key !== '' || value !== '')\n .map(({ key, value }) => ({\n kind: 'env' as const,\n key,\n secondary: value,\n })),\n)\n\ntype FuseRow = DropdownRow & { fuseText: string }\n\nconst envFuseSource = computed((): FuseRow[] =>\n envRows.value.map((row) => ({\n ...row,\n fuseText: `${row.key} ${row.secondary}`,\n })),\n)\n\nconst contextFuseSource = computed((): FuseRow[] =>\n contextRows.value.map((row) => ({\n ...row,\n fuseText: `${row.key} ${row.secondary}`,\n })),\n)\n\nconst fuseEnv = computed(\n () =>\n new Fuse(envFuseSource.value, {\n keys: ['fuseText'],\n threshold: 0.35,\n }),\n)\n\nconst fuseContext = computed(\n () =>\n new Fuse(contextFuseSource.value, {\n keys: ['fuseText'],\n threshold: 0.35,\n }),\n)\n\nconst popularContextRows = computed((): DropdownRow[] => {\n const byKey = new Map(contextFunctionItems.map((c) => [c.key, c]))\n return POPULAR_CONTEXT_FUNCTION_KEYS.flatMap((key) => {\n const item = byKey.get(key)\n return item\n ? [\n {\n kind: 'context' as const,\n key: item.key,\n secondary: item.description,\n },\n ]\n : []\n })\n})\n\nconst DROPDOWN_LIMIT = 12\n\nconst filteredVariables = computed((): DropdownRow[] => {\n if (!query.trim()) {\n const envSlice = envRows.value.slice(-4)\n return [...envSlice, ...popularContextRows.value]\n }\n\n const q = query.trim()\n const envMatches = fuseEnv.value\n .search(q, { limit: DROPDOWN_LIMIT })\n .map((res) => {\n const { kind, key, secondary } = res.item\n return { kind, key, secondary }\n })\n\n const remaining = DROPDOWN_LIMIT - envMatches.length\n const contextMatches =\n remaining > 0\n ? fuseContext.value.search(q, { limit: remaining }).map((res) => {\n const { kind, key, secondary } = res.item\n return { kind, key, secondary }\n })\n : []\n\n return [...envMatches, ...contextMatches]\n})\n\nconst selectVariable = (variableKey: string): void => {\n emit('select', variableKey)\n}\n\nconst handleArrowKey = (direction: 'up' | 'down') => {\n const offset = direction === 'up' ? -1 : 1\n const length = filteredVariables.value.length\n\n if (length === 0) {\n return\n }\n\n selectedVariableIndex.value =\n (selectedVariableIndex.value + offset + length) % length\n}\n\nconst handleSelect = () => {\n if (selectedVariableIndex.value >= 0) {\n const selectedVariable =\n filteredVariables.value[selectedVariableIndex.value]\n if (selectedVariable) {\n selectVariable(selectedVariable.key)\n }\n }\n}\n\ndefineExpose({\n handleArrowKey,\n handleSelect,\n})\n\nonMounted(() => {\n // Reset selected index to the first item when dropdown opens\n selectedVariableIndex.value = 0\n})\n\nconst dropdownStyle = computed<CSSProperties>(() => {\n return {\n left: (dropdownPosition?.left ?? 0) + 'px',\n // Add a 5px offset from the editor\n top: (dropdownPosition?.top ?? 0) + 5 + 'px',\n }\n})\n\nonClickOutside(\n dropdownRef,\n () => {\n isOpen.value = false\n },\n { ignore: [dropdownRef] },\n)\n</script>\n<template>\n <ScalarTeleport\n v-if=\"isOpen\"\n class=\"scalar-client\">\n <div\n ref=\"dropdownRef\"\n class=\"custom-scroll z-context fixed top-0 left-0 flex max-h-[60svh] w-56 flex-col rounded border p-0.75\"\n :style=\"dropdownStyle\">\n <ul\n v-if=\"filteredVariables.length\"\n class=\"gap-1/2 flex flex-col\">\n <template\n v-for=\"(item, index) in filteredVariables\"\n :key=\"`${item.kind}-${item.key}`\">\n <li\n class=\"font-code text-xxs hover:bg-b-2 flex h-8 cursor-pointer items-center justify-between gap-1.5 rounded p-1.5 transition-colors duration-150\"\n :class=\"{ 'bg-b-2': index === selectedVariableIndex }\"\n @click=\"selectVariable(item.key)\">\n <div class=\"flex items-center gap-2 whitespace-nowrap\">\n <span\n v-if=\"item.kind === 'env'\"\n class=\"h-2.25 w-2.25 min-w-2.25 rounded-full\"\n :style=\"{\n backgroundColor: environment.color,\n }\" />\n <span\n v-else\n class=\"text-c-3 bg-b-3 flex h-4.5 min-w-4.5 items-center justify-center rounded px-0.5 font-sans text-[9px] font-semibold\">\n fn\n </span>\n {{ item.key }}\n </div>\n <span\n class=\"max-w-[9rem] overflow-hidden text-right text-ellipsis whitespace-nowrap\">\n {{ item.secondary }}\n </span>\n </li>\n </template>\n </ul>\n <ScalarButton\n v-else\n class=\"font-code text-xxs bg-b-inherit hover:bg-b-2 flex h-8 w-full justify-start gap-2 px-1.5 transition-colors duration-150\"\n variant=\"outlined\"\n @click=\"redirectToEnvironment\">\n <ScalarIconPlus class=\"size-3\" />\n Add Variable\n </ScalarButton>\n <!-- Backdrop for the dropdown -->\n <div\n class=\"bg-b-1 brightness-lifted absolute inset-0 -z-1 rounded shadow-lg\" />\n </div>\n </ScalarTeleport>\n</template>\n"],"mappings":""}
{"version":3,"file":"EnvironmentVariablesDropdown.vue.js","names":[],"sources":["../../../../../src/v2/features/environments/components/EnvironmentVariablesDropdown.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton, ScalarTeleport } from '@scalar/components'\nimport { ScalarIconPlus } from '@scalar/icons'\nimport { POPULAR_CONTEXT_FUNCTION_KEYS } from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { onClickOutside } from '@vueuse/core'\nimport Fuse from 'fuse.js'\nimport { computed, onMounted, ref, type CSSProperties } from 'vue'\n\ntype DropdownRow =\n | { kind: 'env'; key: string; secondary: string }\n | { kind: 'context'; key: string; secondary: string }\n\nconst {\n query,\n environment,\n dropdownPosition,\n contextFunctionItems = [],\n} = defineProps<{\n query: string\n environment?: XScalarEnvironment\n dropdownPosition?: { left: number; top: number }\n /** Runtime placeholders such as `{{$guid}}`, shown with environment variables */\n contextFunctionItems?: { key: string; description: string }[]\n}>()\n\nconst emit = defineEmits<{\n (e: 'select', variable: string): void\n (e: 'redirect'): void\n}>()\n\nconst isOpen = ref(true)\nconst dropdownRef = ref<HTMLElement | null>(null)\nconst selectedVariableIndex = ref(0)\n\nconst redirectToEnvironment = () => {\n emit('redirect')\n isOpen.value = false\n}\n\n/** Normalize the variables to have a name and value */\nconst normalizedVariables = computed(() =>\n (environment?.variables ?? []).map((v) => ({\n key: v.name,\n value: typeof v.value === 'string' ? v.value : v.value.default,\n })),\n)\n\nconst contextRows = computed((): DropdownRow[] =>\n contextFunctionItems.map((item) => ({\n kind: 'context',\n key: item.key,\n secondary: item.description,\n })),\n)\n\nconst envRows = computed((): DropdownRow[] =>\n normalizedVariables.value\n .filter(({ key, value }) => key !== '' || value !== '')\n .map(({ key, value }) => ({\n kind: 'env' as const,\n key,\n secondary: value,\n })),\n)\n\ntype FuseRow = DropdownRow & { fuseText: string }\n\nconst envFuseSource = computed((): FuseRow[] =>\n envRows.value.map((row) => ({\n ...row,\n fuseText: `${row.key} ${row.secondary}`,\n })),\n)\n\nconst contextFuseSource = computed((): FuseRow[] =>\n contextRows.value.map((row) => ({\n ...row,\n fuseText: `${row.key} ${row.secondary}`,\n })),\n)\n\nconst fuseEnv = computed(\n () =>\n new Fuse(envFuseSource.value, {\n keys: ['fuseText'],\n threshold: 0.35,\n }),\n)\n\nconst fuseContext = computed(\n () =>\n new Fuse(contextFuseSource.value, {\n keys: ['fuseText'],\n threshold: 0.35,\n }),\n)\n\nconst popularContextRows = computed((): DropdownRow[] => {\n const byKey = new Map(contextFunctionItems.map((c) => [c.key, c]))\n return POPULAR_CONTEXT_FUNCTION_KEYS.flatMap((key) => {\n const item = byKey.get(key)\n return item\n ? [\n {\n kind: 'context' as const,\n key: item.key,\n secondary: item.description,\n },\n ]\n : []\n })\n})\n\nconst DROPDOWN_LIMIT = 12\n\nconst filteredVariables = computed((): DropdownRow[] => {\n if (!query.trim()) {\n const envSlice = envRows.value.slice(-4)\n return [...envSlice, ...popularContextRows.value]\n }\n\n const q = query.trim()\n const envMatches = fuseEnv.value\n .search(q, { limit: DROPDOWN_LIMIT })\n .map((res) => {\n const { kind, key, secondary } = res.item\n return { kind, key, secondary }\n })\n\n const remaining = DROPDOWN_LIMIT - envMatches.length\n const contextMatches =\n remaining > 0\n ? fuseContext.value.search(q, { limit: remaining }).map((res) => {\n const { kind, key, secondary } = res.item\n return { kind, key, secondary }\n })\n : []\n\n return [...envMatches, ...contextMatches]\n})\n\nconst selectVariable = (variableKey: string): void => {\n emit('select', variableKey)\n}\n\nconst handleArrowKey = (direction: 'up' | 'down') => {\n const offset = direction === 'up' ? -1 : 1\n const length = filteredVariables.value.length\n\n if (length === 0) {\n return\n }\n\n selectedVariableIndex.value =\n (selectedVariableIndex.value + offset + length) % length\n}\n\nconst handleSelect = () => {\n if (selectedVariableIndex.value >= 0) {\n const selectedVariable =\n filteredVariables.value[selectedVariableIndex.value]\n if (selectedVariable) {\n selectVariable(selectedVariable.key)\n }\n }\n}\n\ndefineExpose({\n handleArrowKey,\n handleSelect,\n})\n\nonMounted(() => {\n // Reset selected index to the first item when dropdown opens\n selectedVariableIndex.value = 0\n})\n\nconst dropdownStyle = computed<CSSProperties>(() => {\n return {\n left: (dropdownPosition?.left ?? 0) + 'px',\n // Add a 5px offset from the editor\n top: (dropdownPosition?.top ?? 0) + 5 + 'px',\n }\n})\n\nonClickOutside(\n dropdownRef,\n () => {\n isOpen.value = false\n },\n { ignore: [dropdownRef] },\n)\n</script>\n<template>\n <ScalarTeleport\n v-if=\"isOpen\"\n class=\"scalar-client\">\n <div\n ref=\"dropdownRef\"\n class=\"custom-scroll z-context fixed top-0 left-0 flex max-h-[60svh] w-56 flex-col rounded border p-0.75\"\n :style=\"dropdownStyle\">\n <ul\n v-if=\"filteredVariables.length\"\n class=\"gap-1/2 flex flex-col\">\n <template\n v-for=\"(item, index) in filteredVariables\"\n :key=\"`${item.kind}-${item.key}`\">\n <li\n class=\"font-code text-xxs hover:bg-b-2 flex h-8 cursor-pointer items-center justify-between gap-1.5 rounded p-1.5 transition-colors duration-150\"\n :class=\"{ 'bg-b-2': index === selectedVariableIndex }\"\n @click=\"selectVariable(item.key)\">\n <div class=\"flex items-center gap-2 whitespace-nowrap\">\n <span\n v-if=\"item.kind === 'env'\"\n class=\"h-2.25 w-2.25 min-w-2.25 rounded-full\"\n :style=\"{\n backgroundColor: environment?.color,\n }\" />\n <span\n v-else\n class=\"text-c-3 bg-b-3 flex h-4.5 min-w-4.5 items-center justify-center rounded px-0.5 font-sans text-[9px] font-semibold\">\n fn\n </span>\n {{ item.key }}\n </div>\n <span\n class=\"max-w-[9rem] overflow-hidden text-right text-ellipsis whitespace-nowrap\">\n {{ item.secondary }}\n </span>\n </li>\n </template>\n </ul>\n <ScalarButton\n v-else\n class=\"font-code text-xxs bg-b-inherit hover:bg-b-2 flex h-8 w-full justify-start gap-2 px-1.5 transition-colors duration-150\"\n variant=\"outlined\"\n @click=\"redirectToEnvironment\">\n <ScalarIconPlus class=\"size-3\" />\n Add Variable\n </ScalarButton>\n <!-- Backdrop for the dropdown -->\n <div\n class=\"bg-b-1 brightness-lifted absolute inset-0 -z-1 rounded shadow-lg\" />\n </div>\n </ScalarTeleport>\n</template>\n"],"mappings":""}

@@ -39,3 +39,3 @@ import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, normalizeStyle, onMounted, openBlock, ref, renderList, toDisplayString, unref, withCtx } from "vue";

/** Normalize the variables to have a name and value */
const normalizedVariables = computed(() => __props.environment.variables.map((v) => ({
const normalizedVariables = computed(() => (__props.environment?.variables ?? []).map((v) => ({
key: v.name,

@@ -152,3 +152,3 @@ value: typeof v.value === "string" ? v.value : v.value.default

class: "h-2.25 w-2.25 min-w-2.25 rounded-full",
style: normalizeStyle({ backgroundColor: __props.environment.color })
style: normalizeStyle({ backgroundColor: __props.environment?.color })
}, null, 4)) : (openBlock(), createElementBlock("span", _hoisted_4, " fn ")), createTextVNode(" " + toDisplayString(item.key), 1)]), createElementVNode("span", _hoisted_5, toDisplayString(item.secondary), 1)], 10, _hoisted_2);

@@ -155,0 +155,0 @@ }), 128))])) : (openBlock(), createBlock(unref(ScalarButton), {

@@ -1,1 +0,1 @@

{"version":3,"file":"EnvironmentVariablesDropdown.vue.script.js","names":[],"sources":["../../../../../src/v2/features/environments/components/EnvironmentVariablesDropdown.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton, ScalarTeleport } from '@scalar/components'\nimport { ScalarIconPlus } from '@scalar/icons'\nimport { POPULAR_CONTEXT_FUNCTION_KEYS } from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { onClickOutside } from '@vueuse/core'\nimport Fuse from 'fuse.js'\nimport { computed, onMounted, ref, type CSSProperties } from 'vue'\n\ntype DropdownRow =\n | { kind: 'env'; key: string; secondary: string }\n | { kind: 'context'; key: string; secondary: string }\n\nconst {\n query,\n environment,\n dropdownPosition,\n contextFunctionItems = [],\n} = defineProps<{\n query: string\n environment: XScalarEnvironment\n dropdownPosition?: { left: number; top: number }\n /** Runtime placeholders such as `{{$guid}}`, shown with environment variables */\n contextFunctionItems?: { key: string; description: string }[]\n}>()\n\nconst emit = defineEmits<{\n (e: 'select', variable: string): void\n (e: 'redirect'): void\n}>()\n\nconst isOpen = ref(true)\nconst dropdownRef = ref<HTMLElement | null>(null)\nconst selectedVariableIndex = ref(0)\n\nconst redirectToEnvironment = () => {\n emit('redirect')\n isOpen.value = false\n}\n\n/** Normalize the variables to have a name and value */\nconst normalizedVariables = computed(() =>\n environment.variables.map((v) => ({\n key: v.name,\n value: typeof v.value === 'string' ? v.value : v.value.default,\n })),\n)\n\nconst contextRows = computed((): DropdownRow[] =>\n contextFunctionItems.map((item) => ({\n kind: 'context',\n key: item.key,\n secondary: item.description,\n })),\n)\n\nconst envRows = computed((): DropdownRow[] =>\n normalizedVariables.value\n .filter(({ key, value }) => key !== '' || value !== '')\n .map(({ key, value }) => ({\n kind: 'env' as const,\n key,\n secondary: value,\n })),\n)\n\ntype FuseRow = DropdownRow & { fuseText: string }\n\nconst envFuseSource = computed((): FuseRow[] =>\n envRows.value.map((row) => ({\n ...row,\n fuseText: `${row.key} ${row.secondary}`,\n })),\n)\n\nconst contextFuseSource = computed((): FuseRow[] =>\n contextRows.value.map((row) => ({\n ...row,\n fuseText: `${row.key} ${row.secondary}`,\n })),\n)\n\nconst fuseEnv = computed(\n () =>\n new Fuse(envFuseSource.value, {\n keys: ['fuseText'],\n threshold: 0.35,\n }),\n)\n\nconst fuseContext = computed(\n () =>\n new Fuse(contextFuseSource.value, {\n keys: ['fuseText'],\n threshold: 0.35,\n }),\n)\n\nconst popularContextRows = computed((): DropdownRow[] => {\n const byKey = new Map(contextFunctionItems.map((c) => [c.key, c]))\n return POPULAR_CONTEXT_FUNCTION_KEYS.flatMap((key) => {\n const item = byKey.get(key)\n return item\n ? [\n {\n kind: 'context' as const,\n key: item.key,\n secondary: item.description,\n },\n ]\n : []\n })\n})\n\nconst DROPDOWN_LIMIT = 12\n\nconst filteredVariables = computed((): DropdownRow[] => {\n if (!query.trim()) {\n const envSlice = envRows.value.slice(-4)\n return [...envSlice, ...popularContextRows.value]\n }\n\n const q = query.trim()\n const envMatches = fuseEnv.value\n .search(q, { limit: DROPDOWN_LIMIT })\n .map((res) => {\n const { kind, key, secondary } = res.item\n return { kind, key, secondary }\n })\n\n const remaining = DROPDOWN_LIMIT - envMatches.length\n const contextMatches =\n remaining > 0\n ? fuseContext.value.search(q, { limit: remaining }).map((res) => {\n const { kind, key, secondary } = res.item\n return { kind, key, secondary }\n })\n : []\n\n return [...envMatches, ...contextMatches]\n})\n\nconst selectVariable = (variableKey: string): void => {\n emit('select', variableKey)\n}\n\nconst handleArrowKey = (direction: 'up' | 'down') => {\n const offset = direction === 'up' ? -1 : 1\n const length = filteredVariables.value.length\n\n if (length === 0) {\n return\n }\n\n selectedVariableIndex.value =\n (selectedVariableIndex.value + offset + length) % length\n}\n\nconst handleSelect = () => {\n if (selectedVariableIndex.value >= 0) {\n const selectedVariable =\n filteredVariables.value[selectedVariableIndex.value]\n if (selectedVariable) {\n selectVariable(selectedVariable.key)\n }\n }\n}\n\ndefineExpose({\n handleArrowKey,\n handleSelect,\n})\n\nonMounted(() => {\n // Reset selected index to the first item when dropdown opens\n selectedVariableIndex.value = 0\n})\n\nconst dropdownStyle = computed<CSSProperties>(() => {\n return {\n left: (dropdownPosition?.left ?? 0) + 'px',\n // Add a 5px offset from the editor\n top: (dropdownPosition?.top ?? 0) + 5 + 'px',\n }\n})\n\nonClickOutside(\n dropdownRef,\n () => {\n isOpen.value = false\n },\n { ignore: [dropdownRef] },\n)\n</script>\n<template>\n <ScalarTeleport\n v-if=\"isOpen\"\n class=\"scalar-client\">\n <div\n ref=\"dropdownRef\"\n class=\"custom-scroll z-context fixed top-0 left-0 flex max-h-[60svh] w-56 flex-col rounded border p-0.75\"\n :style=\"dropdownStyle\">\n <ul\n v-if=\"filteredVariables.length\"\n class=\"gap-1/2 flex flex-col\">\n <template\n v-for=\"(item, index) in filteredVariables\"\n :key=\"`${item.kind}-${item.key}`\">\n <li\n class=\"font-code text-xxs hover:bg-b-2 flex h-8 cursor-pointer items-center justify-between gap-1.5 rounded p-1.5 transition-colors duration-150\"\n :class=\"{ 'bg-b-2': index === selectedVariableIndex }\"\n @click=\"selectVariable(item.key)\">\n <div class=\"flex items-center gap-2 whitespace-nowrap\">\n <span\n v-if=\"item.kind === 'env'\"\n class=\"h-2.25 w-2.25 min-w-2.25 rounded-full\"\n :style=\"{\n backgroundColor: environment.color,\n }\" />\n <span\n v-else\n class=\"text-c-3 bg-b-3 flex h-4.5 min-w-4.5 items-center justify-center rounded px-0.5 font-sans text-[9px] font-semibold\">\n fn\n </span>\n {{ item.key }}\n </div>\n <span\n class=\"max-w-[9rem] overflow-hidden text-right text-ellipsis whitespace-nowrap\">\n {{ item.secondary }}\n </span>\n </li>\n </template>\n </ul>\n <ScalarButton\n v-else\n class=\"font-code text-xxs bg-b-inherit hover:bg-b-2 flex h-8 w-full justify-start gap-2 px-1.5 transition-colors duration-150\"\n variant=\"outlined\"\n @click=\"redirectToEnvironment\">\n <ScalarIconPlus class=\"size-3\" />\n Add Variable\n </ScalarButton>\n <!-- Backdrop for the dropdown -->\n <div\n class=\"bg-b-1 brightness-lifted absolute inset-0 -z-1 rounded shadow-lg\" />\n </div>\n </ScalarTeleport>\n</template>\n"],"mappings":"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"}
{"version":3,"file":"EnvironmentVariablesDropdown.vue.script.js","names":[],"sources":["../../../../../src/v2/features/environments/components/EnvironmentVariablesDropdown.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton, ScalarTeleport } from '@scalar/components'\nimport { ScalarIconPlus } from '@scalar/icons'\nimport { POPULAR_CONTEXT_FUNCTION_KEYS } from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { onClickOutside } from '@vueuse/core'\nimport Fuse from 'fuse.js'\nimport { computed, onMounted, ref, type CSSProperties } from 'vue'\n\ntype DropdownRow =\n | { kind: 'env'; key: string; secondary: string }\n | { kind: 'context'; key: string; secondary: string }\n\nconst {\n query,\n environment,\n dropdownPosition,\n contextFunctionItems = [],\n} = defineProps<{\n query: string\n environment?: XScalarEnvironment\n dropdownPosition?: { left: number; top: number }\n /** Runtime placeholders such as `{{$guid}}`, shown with environment variables */\n contextFunctionItems?: { key: string; description: string }[]\n}>()\n\nconst emit = defineEmits<{\n (e: 'select', variable: string): void\n (e: 'redirect'): void\n}>()\n\nconst isOpen = ref(true)\nconst dropdownRef = ref<HTMLElement | null>(null)\nconst selectedVariableIndex = ref(0)\n\nconst redirectToEnvironment = () => {\n emit('redirect')\n isOpen.value = false\n}\n\n/** Normalize the variables to have a name and value */\nconst normalizedVariables = computed(() =>\n (environment?.variables ?? []).map((v) => ({\n key: v.name,\n value: typeof v.value === 'string' ? v.value : v.value.default,\n })),\n)\n\nconst contextRows = computed((): DropdownRow[] =>\n contextFunctionItems.map((item) => ({\n kind: 'context',\n key: item.key,\n secondary: item.description,\n })),\n)\n\nconst envRows = computed((): DropdownRow[] =>\n normalizedVariables.value\n .filter(({ key, value }) => key !== '' || value !== '')\n .map(({ key, value }) => ({\n kind: 'env' as const,\n key,\n secondary: value,\n })),\n)\n\ntype FuseRow = DropdownRow & { fuseText: string }\n\nconst envFuseSource = computed((): FuseRow[] =>\n envRows.value.map((row) => ({\n ...row,\n fuseText: `${row.key} ${row.secondary}`,\n })),\n)\n\nconst contextFuseSource = computed((): FuseRow[] =>\n contextRows.value.map((row) => ({\n ...row,\n fuseText: `${row.key} ${row.secondary}`,\n })),\n)\n\nconst fuseEnv = computed(\n () =>\n new Fuse(envFuseSource.value, {\n keys: ['fuseText'],\n threshold: 0.35,\n }),\n)\n\nconst fuseContext = computed(\n () =>\n new Fuse(contextFuseSource.value, {\n keys: ['fuseText'],\n threshold: 0.35,\n }),\n)\n\nconst popularContextRows = computed((): DropdownRow[] => {\n const byKey = new Map(contextFunctionItems.map((c) => [c.key, c]))\n return POPULAR_CONTEXT_FUNCTION_KEYS.flatMap((key) => {\n const item = byKey.get(key)\n return item\n ? [\n {\n kind: 'context' as const,\n key: item.key,\n secondary: item.description,\n },\n ]\n : []\n })\n})\n\nconst DROPDOWN_LIMIT = 12\n\nconst filteredVariables = computed((): DropdownRow[] => {\n if (!query.trim()) {\n const envSlice = envRows.value.slice(-4)\n return [...envSlice, ...popularContextRows.value]\n }\n\n const q = query.trim()\n const envMatches = fuseEnv.value\n .search(q, { limit: DROPDOWN_LIMIT })\n .map((res) => {\n const { kind, key, secondary } = res.item\n return { kind, key, secondary }\n })\n\n const remaining = DROPDOWN_LIMIT - envMatches.length\n const contextMatches =\n remaining > 0\n ? fuseContext.value.search(q, { limit: remaining }).map((res) => {\n const { kind, key, secondary } = res.item\n return { kind, key, secondary }\n })\n : []\n\n return [...envMatches, ...contextMatches]\n})\n\nconst selectVariable = (variableKey: string): void => {\n emit('select', variableKey)\n}\n\nconst handleArrowKey = (direction: 'up' | 'down') => {\n const offset = direction === 'up' ? -1 : 1\n const length = filteredVariables.value.length\n\n if (length === 0) {\n return\n }\n\n selectedVariableIndex.value =\n (selectedVariableIndex.value + offset + length) % length\n}\n\nconst handleSelect = () => {\n if (selectedVariableIndex.value >= 0) {\n const selectedVariable =\n filteredVariables.value[selectedVariableIndex.value]\n if (selectedVariable) {\n selectVariable(selectedVariable.key)\n }\n }\n}\n\ndefineExpose({\n handleArrowKey,\n handleSelect,\n})\n\nonMounted(() => {\n // Reset selected index to the first item when dropdown opens\n selectedVariableIndex.value = 0\n})\n\nconst dropdownStyle = computed<CSSProperties>(() => {\n return {\n left: (dropdownPosition?.left ?? 0) + 'px',\n // Add a 5px offset from the editor\n top: (dropdownPosition?.top ?? 0) + 5 + 'px',\n }\n})\n\nonClickOutside(\n dropdownRef,\n () => {\n isOpen.value = false\n },\n { ignore: [dropdownRef] },\n)\n</script>\n<template>\n <ScalarTeleport\n v-if=\"isOpen\"\n class=\"scalar-client\">\n <div\n ref=\"dropdownRef\"\n class=\"custom-scroll z-context fixed top-0 left-0 flex max-h-[60svh] w-56 flex-col rounded border p-0.75\"\n :style=\"dropdownStyle\">\n <ul\n v-if=\"filteredVariables.length\"\n class=\"gap-1/2 flex flex-col\">\n <template\n v-for=\"(item, index) in filteredVariables\"\n :key=\"`${item.kind}-${item.key}`\">\n <li\n class=\"font-code text-xxs hover:bg-b-2 flex h-8 cursor-pointer items-center justify-between gap-1.5 rounded p-1.5 transition-colors duration-150\"\n :class=\"{ 'bg-b-2': index === selectedVariableIndex }\"\n @click=\"selectVariable(item.key)\">\n <div class=\"flex items-center gap-2 whitespace-nowrap\">\n <span\n v-if=\"item.kind === 'env'\"\n class=\"h-2.25 w-2.25 min-w-2.25 rounded-full\"\n :style=\"{\n backgroundColor: environment?.color,\n }\" />\n <span\n v-else\n class=\"text-c-3 bg-b-3 flex h-4.5 min-w-4.5 items-center justify-center rounded px-0.5 font-sans text-[9px] font-semibold\">\n fn\n </span>\n {{ item.key }}\n </div>\n <span\n class=\"max-w-[9rem] overflow-hidden text-right text-ellipsis whitespace-nowrap\">\n {{ item.secondary }}\n </span>\n </li>\n </template>\n </ul>\n <ScalarButton\n v-else\n class=\"font-code text-xxs bg-b-inherit hover:bg-b-2 flex h-8 w-full justify-start gap-2 px-1.5 transition-colors duration-150\"\n variant=\"outlined\"\n @click=\"redirectToEnvironment\">\n <ScalarIconPlus class=\"size-3\" />\n Add Variable\n </ScalarButton>\n <!-- Backdrop for the dropdown -->\n <div\n class=\"bg-b-1 brightness-lifted absolute inset-0 -z-1 rounded shadow-lg\" />\n </div>\n </ScalarTeleport>\n</template>\n"],"mappings":"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"}

@@ -1,1 +0,1 @@

{"version":3,"file":"CookiesTable.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/global-cookies/components/CookiesTable.vue"],"names":[],"mappings":"AAuPA,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EAClB,MAAM,gCAAgC,CAAA;AACvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qEAAqE,CAAA;AAYxG,KAAK,WAAW,GAAG;IACf,OAAO,EAAE,aAAa,EAAE,CAAA;IACxB,QAAQ,EAAE,iBAAiB,CAAA;CAC5B,GAAG,cAAc,CAAC;AA8erB,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
{"version":3,"file":"CookiesTable.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/global-cookies/components/CookiesTable.vue"],"names":[],"mappings":"AAyPA,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EAClB,MAAM,gCAAgC,CAAA;AACvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qEAAqE,CAAA;AAYxG,KAAK,WAAW,GAAG;IACf,OAAO,EAAE,aAAa,EAAE,CAAA;IACxB,QAAQ,EAAE,iBAAiB,CAAA;CAC5B,GAAG,cAAc,CAAC;AAkfrB,QAAA,MAAM,YAAY,kSAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}

@@ -5,3 +5,3 @@ import _plugin_vue_export_helper_default from "../../../../_virtual/_plugin-vue_export-helper.js";

//#region src/v2/features/global-cookies/components/CookiesTable.vue
var CookiesTable_default = /* @__PURE__ */ _plugin_vue_export_helper_default(CookiesTable_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-ddfccc08"]]);
var CookiesTable_default = /* @__PURE__ */ _plugin_vue_export_helper_default(CookiesTable_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-2f13118d"]]);
//#endregion

@@ -8,0 +8,0 @@ export { CookiesTable_default as default };

@@ -1,1 +0,1 @@

{"version":3,"file":"CookiesTable.vue.js","names":[],"sources":["../../../../../src/v2/features/global-cookies/components/CookiesTable.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components'\nimport { ScalarIconTrash } from '@scalar/icons'\nimport type {\n CollectionType,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport { computed } from 'vue'\n\nimport { CodeInput } from '@/v2/components/code-input'\nimport {\n DataTable,\n DataTableCell,\n DataTableCheckbox,\n DataTableHeader,\n DataTableRow,\n} from '@/v2/components/data-table'\n\nconst { cookies, eventBus, collectionType } = defineProps<\n {\n cookies: XScalarCookie[]\n eventBus: WorkspaceEventBus\n } & CollectionType\n>()\n\n/** Column widths: Enabled checkbox, Name, Value, Domain, Actions (delete button) */\nconst COLUMNS = ['32px', '1fr', '1fr', '1fr', '36px']\n\n/** Adds an empty row at the end for creating new cookies */\nconst displayRows = computed<\n {\n name: string\n value: string\n domain: string\n isDisabled: boolean\n }[]\n>(() => {\n /** Normalize the cookies to have name, value, and domain */\n const cookieRows = cookies.map((cookie) => ({\n name: cookie.name,\n value: cookie.value,\n domain: cookie.domain ?? '',\n isDisabled: cookie.isDisabled ?? false,\n }))\n\n const lastCookie = cookies.at(-1)\n const hasContentInLastRow =\n lastCookie &&\n (lastCookie.name !== '' ||\n lastCookie.value !== '' ||\n lastCookie.domain !== '')\n\n // Add the extra row at the end\n if (!lastCookie || hasContentInLastRow) {\n return [\n ...cookieRows,\n { name: '', value: '', domain: '', isDisabled: true },\n ]\n }\n\n return cookieRows\n})\n\n/** Updates an existing cookie or creates a new one */\nconst handleCookieChange = (\n name: string,\n value: string,\n domain: string,\n isDisabled: boolean,\n index: number,\n): void => {\n const isNewCookie = index >= cookies.length\n\n /**\n * Do not allow adding a new cookie with an empty name on the last row,\n * we allow it on other rows as it will delete the row\n */\n if (!name && isNewCookie) {\n return\n }\n\n // Adding a new cookie\n if (index >= cookies.length) {\n eventBus.emit('cookie:upsert:cookie', {\n payload: { name, value, domain, isDisabled: false },\n collectionType,\n })\n return\n }\n\n // Updating existing cookie\n eventBus.emit('cookie:upsert:cookie', {\n payload: { name, value, domain, isDisabled },\n collectionType,\n index,\n })\n}\n\n/** Deletes a cookie by index */\nconst handleCookieDelete = (index: number): void =>\n eventBus.emit('cookie:delete:cookie', {\n cookieName: cookies[index]?.name ?? '',\n index,\n collectionType,\n })\n</script>\n<template>\n <!-- Cookies table -->\n <DataTable\n class=\"group/table data-table h-min flex-1 rounded border border-t-0\"\n :columns=\"COLUMNS\">\n <!-- Accessibility header row -->\n <DataTableRow class=\"sr-only !block\">\n <DataTableHeader>Enabled</DataTableHeader>\n <DataTableHeader>Name</DataTableHeader>\n <DataTableHeader>Value</DataTableHeader>\n <DataTableHeader>Domain</DataTableHeader>\n <DataTableHeader>Actions</DataTableHeader>\n </DataTableRow>\n\n <!-- Cookie rows -->\n <DataTableRow\n v-for=\"(row, index) in displayRows\"\n :key=\"index\"\n class=\"group/row\">\n <!-- Enabled checkbox -->\n <DataTableCheckbox\n class=\"!border-r\"\n :modelValue=\"!row.isDisabled\"\n @update:modelValue=\"\n (value) =>\n handleCookieChange(row.name, row.value, row.domain, !value, index)\n \" />\n\n <!-- Name -->\n <DataTableCell>\n <CodeInput\n aria-label=\"Cookie Name\"\n disableCloseBrackets\n disableTabIndent\n :environment=\"undefined\"\n lineWrapping\n :modelValue=\"row.name\"\n placeholder=\"Name\"\n @update:modelValue=\"\n (name) =>\n handleCookieChange(\n name,\n row.value,\n row.domain,\n row.isDisabled,\n index,\n )\n \" />\n </DataTableCell>\n\n <!-- Value -->\n <DataTableCell>\n <CodeInput\n aria-label=\"Cookie Value\"\n disableTabIndent\n :environment=\"undefined\"\n lineWrapping\n :modelValue=\"row.value\"\n placeholder=\"Value\"\n @update:modelValue=\"\n (value) =>\n handleCookieChange(\n row.name,\n value,\n row.domain,\n row.isDisabled,\n index,\n )\n \" />\n </DataTableCell>\n\n <!-- Domain -->\n <DataTableCell>\n <CodeInput\n aria-label=\"Cookie Domain\"\n disableCloseBrackets\n disableTabIndent\n :environment=\"undefined\"\n lineWrapping\n :modelValue=\"row.domain\"\n placeholder=\"Domain\"\n @update:modelValue=\"\n (domain) =>\n handleCookieChange(\n row.name,\n row.value,\n domain,\n row.isDisabled,\n index,\n )\n \" />\n </DataTableCell>\n\n <!-- Delete button -->\n <DataTableCell class=\"flex items-center justify-center\">\n <ScalarButton\n v-if=\"index < cookies.length\"\n class=\"text-c-2 hover:text-c-1 hover:bg-b-2 hidden h-fit rounded p-1 group-focus-within:flex group-hover/row:flex\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"handleCookieDelete(index)\">\n <ScalarIconTrash class=\"size-3.5\" />\n </ScalarButton>\n </DataTableCell>\n </DataTableRow>\n </DataTable>\n</template>\n<style scoped>\n:deep(.cm-editor) {\n padding: 0;\n}\n:deep(.cm-content) {\n align-items: center;\n background-color: transparent;\n display: flex;\n font-family: var(--scalar-font);\n font-size: var(--scalar-small);\n padding: 5px 8px;\n width: 100%;\n}\n:deep(.cm-content):has(.cm-pill) {\n padding: 5px 8px;\n}\n:deep(.cm-content .cm-pill:not(:last-of-type)) {\n margin-right: 0.5px;\n}\n:deep(.cm-content .cm-pill:not(:first-of-type)) {\n margin-left: 0.5px;\n}\n:deep(.cm-line) {\n overflow: hidden;\n padding: 0;\n text-overflow: ellipsis;\n}\n</style>\n"],"mappings":""}
{"version":3,"file":"CookiesTable.vue.js","names":[],"sources":["../../../../../src/v2/features/global-cookies/components/CookiesTable.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components'\nimport { ScalarIconTrash } from '@scalar/icons'\nimport type {\n CollectionType,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport { computed } from 'vue'\n\nimport { CodeInput } from '@/v2/components/code-input'\nimport {\n DataTable,\n DataTableCell,\n DataTableCheckbox,\n DataTableHeader,\n DataTableRow,\n} from '@/v2/components/data-table'\n\nconst { cookies, eventBus, collectionType } = defineProps<\n {\n cookies: XScalarCookie[]\n eventBus: WorkspaceEventBus\n } & CollectionType\n>()\n\n/** Column widths: Enabled checkbox, Name, Value, Domain, Actions (delete button) */\nconst COLUMNS = ['32px', '1fr', '1fr', '1fr', '36px']\n\n/** Adds an empty row at the end for creating new cookies */\nconst displayRows = computed<\n {\n name: string\n value: string\n domain: string\n isDisabled: boolean\n }[]\n>(() => {\n /** Normalize the cookies to have name, value, and domain */\n const cookieRows = cookies.map((cookie) => ({\n name: cookie.name,\n value: cookie.value,\n domain: cookie.domain ?? '',\n isDisabled: cookie.isDisabled ?? false,\n }))\n\n const lastCookie = cookies.at(-1)\n const hasContentInLastRow =\n lastCookie &&\n (lastCookie.name !== '' ||\n lastCookie.value !== '' ||\n lastCookie.domain !== '')\n\n // Add the extra row at the end\n if (!lastCookie || hasContentInLastRow) {\n return [\n ...cookieRows,\n { name: '', value: '', domain: '', isDisabled: true },\n ]\n }\n\n return cookieRows\n})\n\n/** Updates an existing cookie or creates a new one */\nconst handleCookieChange = (\n name: string,\n value: string,\n domain: string,\n isDisabled: boolean,\n index: number,\n): void => {\n const isNewCookie = index >= cookies.length\n\n /**\n * Do not allow adding a new cookie with an empty name on the last row,\n * we allow it on other rows as it will delete the row\n */\n if (!name && isNewCookie) {\n return\n }\n\n // Adding a new cookie\n if (index >= cookies.length) {\n eventBus.emit('cookie:upsert:cookie', {\n payload: { name, value, domain, isDisabled: false },\n collectionType,\n })\n return\n }\n\n // Updating existing cookie\n eventBus.emit('cookie:upsert:cookie', {\n payload: { name, value, domain, isDisabled },\n collectionType,\n index,\n })\n}\n\n/** Deletes a cookie by index */\nconst handleCookieDelete = (index: number): void =>\n eventBus.emit('cookie:delete:cookie', {\n cookieName: cookies[index]?.name ?? '',\n index,\n collectionType,\n })\n</script>\n<template>\n <!-- Cookies table -->\n <DataTable\n class=\"group/table data-table h-min flex-1 rounded border border-t-0\"\n :columns=\"COLUMNS\">\n <!-- Accessibility header row -->\n <DataTableRow class=\"sr-only !block\">\n <DataTableHeader>Enabled</DataTableHeader>\n <DataTableHeader>Name</DataTableHeader>\n <DataTableHeader>Value</DataTableHeader>\n <DataTableHeader>Domain</DataTableHeader>\n <DataTableHeader>Actions</DataTableHeader>\n </DataTableRow>\n\n <!-- Cookie rows -->\n <DataTableRow\n v-for=\"(row, index) in displayRows\"\n :key=\"index\"\n class=\"group/row\">\n <!-- Enabled checkbox -->\n <DataTableCheckbox\n class=\"!border-r\"\n :modelValue=\"!row.isDisabled\"\n @update:modelValue=\"\n (value) =>\n handleCookieChange(row.name, row.value, row.domain, !value, index)\n \" />\n\n <!-- Name -->\n <DataTableCell>\n <CodeInput\n aria-label=\"Cookie Name\"\n disableCloseBrackets\n disableTabIndent\n :environment=\"undefined\"\n lineWrapping\n :modelValue=\"row.name\"\n placeholder=\"Name\"\n @update:modelValue=\"\n (name) =>\n handleCookieChange(\n name,\n row.value,\n row.domain,\n row.isDisabled,\n index,\n )\n \" />\n </DataTableCell>\n\n <!-- Value -->\n <DataTableCell>\n <CodeInput\n aria-label=\"Cookie Value\"\n disableCloseBrackets\n disableTabIndent\n :environment=\"undefined\"\n lineWrapping\n :modelValue=\"row.value\"\n placeholder=\"Value\"\n withFakeData\n @update:modelValue=\"\n (value) =>\n handleCookieChange(\n row.name,\n value,\n row.domain,\n row.isDisabled,\n index,\n )\n \" />\n </DataTableCell>\n\n <!-- Domain -->\n <DataTableCell>\n <CodeInput\n aria-label=\"Cookie Domain\"\n disableCloseBrackets\n disableTabIndent\n :environment=\"undefined\"\n lineWrapping\n :modelValue=\"row.domain\"\n placeholder=\"Domain\"\n @update:modelValue=\"\n (domain) =>\n handleCookieChange(\n row.name,\n row.value,\n domain,\n row.isDisabled,\n index,\n )\n \" />\n </DataTableCell>\n\n <!-- Delete button -->\n <DataTableCell class=\"flex items-center justify-center\">\n <ScalarButton\n v-if=\"index < cookies.length\"\n class=\"text-c-2 hover:text-c-1 hover:bg-b-2 hidden h-fit rounded p-1 group-focus-within:flex group-hover/row:flex\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"handleCookieDelete(index)\">\n <ScalarIconTrash class=\"size-3.5\" />\n </ScalarButton>\n </DataTableCell>\n </DataTableRow>\n </DataTable>\n</template>\n<style scoped>\n:deep(.cm-editor) {\n padding: 0;\n}\n:deep(.cm-content) {\n align-items: center;\n background-color: transparent;\n display: flex;\n font-family: var(--scalar-font);\n font-size: var(--scalar-small);\n padding: 5px 8px;\n width: 100%;\n}\n:deep(.cm-content):has(.cm-pill) {\n padding: 5px 8px;\n}\n:deep(.cm-content .cm-pill:not(:last-of-type)) {\n margin-right: 0.5px;\n}\n:deep(.cm-content .cm-pill:not(:first-of-type)) {\n margin-left: 0.5px;\n}\n:deep(.cm-line) {\n overflow: hidden;\n padding: 0;\n text-overflow: ellipsis;\n}\n</style>\n"],"mappings":""}

@@ -139,2 +139,3 @@ import CodeInput_default from "../../../components/code-input/CodeInput.vue.js";

"aria-label": "Cookie Value",
disableCloseBrackets: "",
disableTabIndent: "",

@@ -145,2 +146,3 @@ environment: void 0,

placeholder: "Value",
withFakeData: "",
"onUpdate:modelValue": (value) => handleCookieChange(row.name, value, row.domain, row.isDisabled, index)

@@ -147,0 +149,0 @@ }, null, 8, ["modelValue", "onUpdate:modelValue"])]),

@@ -1,1 +0,1 @@

{"version":3,"file":"CookiesTable.vue.script.js","names":[],"sources":["../../../../../src/v2/features/global-cookies/components/CookiesTable.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components'\nimport { ScalarIconTrash } from '@scalar/icons'\nimport type {\n CollectionType,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport { computed } from 'vue'\n\nimport { CodeInput } from '@/v2/components/code-input'\nimport {\n DataTable,\n DataTableCell,\n DataTableCheckbox,\n DataTableHeader,\n DataTableRow,\n} from '@/v2/components/data-table'\n\nconst { cookies, eventBus, collectionType } = defineProps<\n {\n cookies: XScalarCookie[]\n eventBus: WorkspaceEventBus\n } & CollectionType\n>()\n\n/** Column widths: Enabled checkbox, Name, Value, Domain, Actions (delete button) */\nconst COLUMNS = ['32px', '1fr', '1fr', '1fr', '36px']\n\n/** Adds an empty row at the end for creating new cookies */\nconst displayRows = computed<\n {\n name: string\n value: string\n domain: string\n isDisabled: boolean\n }[]\n>(() => {\n /** Normalize the cookies to have name, value, and domain */\n const cookieRows = cookies.map((cookie) => ({\n name: cookie.name,\n value: cookie.value,\n domain: cookie.domain ?? '',\n isDisabled: cookie.isDisabled ?? false,\n }))\n\n const lastCookie = cookies.at(-1)\n const hasContentInLastRow =\n lastCookie &&\n (lastCookie.name !== '' ||\n lastCookie.value !== '' ||\n lastCookie.domain !== '')\n\n // Add the extra row at the end\n if (!lastCookie || hasContentInLastRow) {\n return [\n ...cookieRows,\n { name: '', value: '', domain: '', isDisabled: true },\n ]\n }\n\n return cookieRows\n})\n\n/** Updates an existing cookie or creates a new one */\nconst handleCookieChange = (\n name: string,\n value: string,\n domain: string,\n isDisabled: boolean,\n index: number,\n): void => {\n const isNewCookie = index >= cookies.length\n\n /**\n * Do not allow adding a new cookie with an empty name on the last row,\n * we allow it on other rows as it will delete the row\n */\n if (!name && isNewCookie) {\n return\n }\n\n // Adding a new cookie\n if (index >= cookies.length) {\n eventBus.emit('cookie:upsert:cookie', {\n payload: { name, value, domain, isDisabled: false },\n collectionType,\n })\n return\n }\n\n // Updating existing cookie\n eventBus.emit('cookie:upsert:cookie', {\n payload: { name, value, domain, isDisabled },\n collectionType,\n index,\n })\n}\n\n/** Deletes a cookie by index */\nconst handleCookieDelete = (index: number): void =>\n eventBus.emit('cookie:delete:cookie', {\n cookieName: cookies[index]?.name ?? '',\n index,\n collectionType,\n })\n</script>\n<template>\n <!-- Cookies table -->\n <DataTable\n class=\"group/table data-table h-min flex-1 rounded border border-t-0\"\n :columns=\"COLUMNS\">\n <!-- Accessibility header row -->\n <DataTableRow class=\"sr-only !block\">\n <DataTableHeader>Enabled</DataTableHeader>\n <DataTableHeader>Name</DataTableHeader>\n <DataTableHeader>Value</DataTableHeader>\n <DataTableHeader>Domain</DataTableHeader>\n <DataTableHeader>Actions</DataTableHeader>\n </DataTableRow>\n\n <!-- Cookie rows -->\n <DataTableRow\n v-for=\"(row, index) in displayRows\"\n :key=\"index\"\n class=\"group/row\">\n <!-- Enabled checkbox -->\n <DataTableCheckbox\n class=\"!border-r\"\n :modelValue=\"!row.isDisabled\"\n @update:modelValue=\"\n (value) =>\n handleCookieChange(row.name, row.value, row.domain, !value, index)\n \" />\n\n <!-- Name -->\n <DataTableCell>\n <CodeInput\n aria-label=\"Cookie Name\"\n disableCloseBrackets\n disableTabIndent\n :environment=\"undefined\"\n lineWrapping\n :modelValue=\"row.name\"\n placeholder=\"Name\"\n @update:modelValue=\"\n (name) =>\n handleCookieChange(\n name,\n row.value,\n row.domain,\n row.isDisabled,\n index,\n )\n \" />\n </DataTableCell>\n\n <!-- Value -->\n <DataTableCell>\n <CodeInput\n aria-label=\"Cookie Value\"\n disableTabIndent\n :environment=\"undefined\"\n lineWrapping\n :modelValue=\"row.value\"\n placeholder=\"Value\"\n @update:modelValue=\"\n (value) =>\n handleCookieChange(\n row.name,\n value,\n row.domain,\n row.isDisabled,\n index,\n )\n \" />\n </DataTableCell>\n\n <!-- Domain -->\n <DataTableCell>\n <CodeInput\n aria-label=\"Cookie Domain\"\n disableCloseBrackets\n disableTabIndent\n :environment=\"undefined\"\n lineWrapping\n :modelValue=\"row.domain\"\n placeholder=\"Domain\"\n @update:modelValue=\"\n (domain) =>\n handleCookieChange(\n row.name,\n row.value,\n domain,\n row.isDisabled,\n index,\n )\n \" />\n </DataTableCell>\n\n <!-- Delete button -->\n <DataTableCell class=\"flex items-center justify-center\">\n <ScalarButton\n v-if=\"index < cookies.length\"\n class=\"text-c-2 hover:text-c-1 hover:bg-b-2 hidden h-fit rounded p-1 group-focus-within:flex group-hover/row:flex\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"handleCookieDelete(index)\">\n <ScalarIconTrash class=\"size-3.5\" />\n </ScalarButton>\n </DataTableCell>\n </DataTableRow>\n </DataTable>\n</template>\n<style scoped>\n:deep(.cm-editor) {\n padding: 0;\n}\n:deep(.cm-content) {\n align-items: center;\n background-color: transparent;\n display: flex;\n font-family: var(--scalar-font);\n font-size: var(--scalar-small);\n padding: 5px 8px;\n width: 100%;\n}\n:deep(.cm-content):has(.cm-pill) {\n padding: 5px 8px;\n}\n:deep(.cm-content .cm-pill:not(:last-of-type)) {\n margin-right: 0.5px;\n}\n:deep(.cm-content .cm-pill:not(:first-of-type)) {\n margin-left: 0.5px;\n}\n:deep(.cm-line) {\n overflow: hidden;\n padding: 0;\n text-overflow: ellipsis;\n}\n</style>\n"],"mappings":"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"}
{"version":3,"file":"CookiesTable.vue.script.js","names":[],"sources":["../../../../../src/v2/features/global-cookies/components/CookiesTable.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components'\nimport { ScalarIconTrash } from '@scalar/icons'\nimport type {\n CollectionType,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport type { XScalarCookie } from '@scalar/workspace-store/schemas/extensions/general/x-scalar-cookies'\nimport { computed } from 'vue'\n\nimport { CodeInput } from '@/v2/components/code-input'\nimport {\n DataTable,\n DataTableCell,\n DataTableCheckbox,\n DataTableHeader,\n DataTableRow,\n} from '@/v2/components/data-table'\n\nconst { cookies, eventBus, collectionType } = defineProps<\n {\n cookies: XScalarCookie[]\n eventBus: WorkspaceEventBus\n } & CollectionType\n>()\n\n/** Column widths: Enabled checkbox, Name, Value, Domain, Actions (delete button) */\nconst COLUMNS = ['32px', '1fr', '1fr', '1fr', '36px']\n\n/** Adds an empty row at the end for creating new cookies */\nconst displayRows = computed<\n {\n name: string\n value: string\n domain: string\n isDisabled: boolean\n }[]\n>(() => {\n /** Normalize the cookies to have name, value, and domain */\n const cookieRows = cookies.map((cookie) => ({\n name: cookie.name,\n value: cookie.value,\n domain: cookie.domain ?? '',\n isDisabled: cookie.isDisabled ?? false,\n }))\n\n const lastCookie = cookies.at(-1)\n const hasContentInLastRow =\n lastCookie &&\n (lastCookie.name !== '' ||\n lastCookie.value !== '' ||\n lastCookie.domain !== '')\n\n // Add the extra row at the end\n if (!lastCookie || hasContentInLastRow) {\n return [\n ...cookieRows,\n { name: '', value: '', domain: '', isDisabled: true },\n ]\n }\n\n return cookieRows\n})\n\n/** Updates an existing cookie or creates a new one */\nconst handleCookieChange = (\n name: string,\n value: string,\n domain: string,\n isDisabled: boolean,\n index: number,\n): void => {\n const isNewCookie = index >= cookies.length\n\n /**\n * Do not allow adding a new cookie with an empty name on the last row,\n * we allow it on other rows as it will delete the row\n */\n if (!name && isNewCookie) {\n return\n }\n\n // Adding a new cookie\n if (index >= cookies.length) {\n eventBus.emit('cookie:upsert:cookie', {\n payload: { name, value, domain, isDisabled: false },\n collectionType,\n })\n return\n }\n\n // Updating existing cookie\n eventBus.emit('cookie:upsert:cookie', {\n payload: { name, value, domain, isDisabled },\n collectionType,\n index,\n })\n}\n\n/** Deletes a cookie by index */\nconst handleCookieDelete = (index: number): void =>\n eventBus.emit('cookie:delete:cookie', {\n cookieName: cookies[index]?.name ?? '',\n index,\n collectionType,\n })\n</script>\n<template>\n <!-- Cookies table -->\n <DataTable\n class=\"group/table data-table h-min flex-1 rounded border border-t-0\"\n :columns=\"COLUMNS\">\n <!-- Accessibility header row -->\n <DataTableRow class=\"sr-only !block\">\n <DataTableHeader>Enabled</DataTableHeader>\n <DataTableHeader>Name</DataTableHeader>\n <DataTableHeader>Value</DataTableHeader>\n <DataTableHeader>Domain</DataTableHeader>\n <DataTableHeader>Actions</DataTableHeader>\n </DataTableRow>\n\n <!-- Cookie rows -->\n <DataTableRow\n v-for=\"(row, index) in displayRows\"\n :key=\"index\"\n class=\"group/row\">\n <!-- Enabled checkbox -->\n <DataTableCheckbox\n class=\"!border-r\"\n :modelValue=\"!row.isDisabled\"\n @update:modelValue=\"\n (value) =>\n handleCookieChange(row.name, row.value, row.domain, !value, index)\n \" />\n\n <!-- Name -->\n <DataTableCell>\n <CodeInput\n aria-label=\"Cookie Name\"\n disableCloseBrackets\n disableTabIndent\n :environment=\"undefined\"\n lineWrapping\n :modelValue=\"row.name\"\n placeholder=\"Name\"\n @update:modelValue=\"\n (name) =>\n handleCookieChange(\n name,\n row.value,\n row.domain,\n row.isDisabled,\n index,\n )\n \" />\n </DataTableCell>\n\n <!-- Value -->\n <DataTableCell>\n <CodeInput\n aria-label=\"Cookie Value\"\n disableCloseBrackets\n disableTabIndent\n :environment=\"undefined\"\n lineWrapping\n :modelValue=\"row.value\"\n placeholder=\"Value\"\n withFakeData\n @update:modelValue=\"\n (value) =>\n handleCookieChange(\n row.name,\n value,\n row.domain,\n row.isDisabled,\n index,\n )\n \" />\n </DataTableCell>\n\n <!-- Domain -->\n <DataTableCell>\n <CodeInput\n aria-label=\"Cookie Domain\"\n disableCloseBrackets\n disableTabIndent\n :environment=\"undefined\"\n lineWrapping\n :modelValue=\"row.domain\"\n placeholder=\"Domain\"\n @update:modelValue=\"\n (domain) =>\n handleCookieChange(\n row.name,\n row.value,\n domain,\n row.isDisabled,\n index,\n )\n \" />\n </DataTableCell>\n\n <!-- Delete button -->\n <DataTableCell class=\"flex items-center justify-center\">\n <ScalarButton\n v-if=\"index < cookies.length\"\n class=\"text-c-2 hover:text-c-1 hover:bg-b-2 hidden h-fit rounded p-1 group-focus-within:flex group-hover/row:flex\"\n size=\"sm\"\n variant=\"ghost\"\n @click=\"handleCookieDelete(index)\">\n <ScalarIconTrash class=\"size-3.5\" />\n </ScalarButton>\n </DataTableCell>\n </DataTableRow>\n </DataTable>\n</template>\n<style scoped>\n:deep(.cm-editor) {\n padding: 0;\n}\n:deep(.cm-content) {\n align-items: center;\n background-color: transparent;\n display: flex;\n font-family: var(--scalar-font);\n font-size: var(--scalar-small);\n padding: 5px 8px;\n width: 100%;\n}\n:deep(.cm-content):has(.cm-pill) {\n padding: 5px 8px;\n}\n:deep(.cm-content .cm-pill:not(:last-of-type)) {\n margin-right: 0.5px;\n}\n:deep(.cm-content .cm-pill:not(:first-of-type)) {\n margin-left: 0.5px;\n}\n:deep(.cm-line) {\n overflow: hidden;\n padding: 0;\n text-overflow: ellipsis;\n}\n</style>\n"],"mappings":"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"}

@@ -7,4 +7,4 @@ import { type ModalState } from '@scalar/components';

import { type RoutePayload } from '../../../../v2/features/modal/helpers/resolve-route-parameters.js';
import type { ApiClientModalOptions } from '../../../../v2/features/modal/helpers/types';
type CreateApiClientModalOptions = {
import type { ApiClientOptions } from '../../../../v2/types/options';
type CreateApiClientOptions = {
/** Element to mount the client modal to. */

@@ -24,3 +24,3 @@ el: HTMLElement | null;

/** Subset of the configuration options for the modal, if you want it to be reactive ensure its a ref */
options?: MaybeRefOrGetter<ApiClientModalOptions>;
options?: MaybeRefOrGetter<ApiClientOptions>;
};

@@ -32,3 +32,3 @@ export type ApiClientModal = {

route: (payload: RoutePayload) => void;
updateOptions: (nextOptions: ApiClientModalOptions, overwrite?: boolean) => void;
updateOptions: (nextOptions: ApiClientOptions, overwrite?: boolean) => void;
modalState: ModalState;

@@ -42,4 +42,4 @@ };

*/
export declare const createApiClientModal: ({ el, eventBus, mountOnInitialize, plugins, workspaceStore, options, }: CreateApiClientModalOptions) => ApiClientModal;
export declare const createApiClientModal: ({ el, eventBus, mountOnInitialize, plugins, workspaceStore, options, }: CreateApiClientOptions) => ApiClientModal;
export {};
//# sourceMappingURL=create-api-client-modal.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"create-api-client-modal.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/modal/helpers/create-api-client-modal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAY,MAAM,oBAAoB,CAAA;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,EAAE,KAAK,iBAAiB,EAA2B,MAAM,gCAAgC,CAAA;AAChG,OAAO,EAAE,KAAK,GAAG,EAAE,KAAK,gBAAgB,EAA6D,MAAM,KAAK,CAAA;AAEhH,OAAO,EAEL,KAAK,YAAY,EAElB,MAAM,sDAAsD,CAAA;AAC7D,OAAO,KAAK,EAAE,qBAAqB,EAA4B,MAAM,mCAAmC,CAAA;AAIxG,KAAK,2BAA2B,GAAG;IACjC,4CAA4C;IAC5C,EAAE,EAAE,WAAW,GAAG,IAAI,CAAA;IACtB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,kFAAkF;IAClF,QAAQ,CAAC,EAAE,iBAAiB,CAAA;IAC5B,6DAA6D;IAC7D,cAAc,EAAE,cAAc,CAAA;IAC9B,iDAAiD;IACjD,OAAO,CAAC,EAAE,YAAY,EAAE,CAAA;IACxB,wGAAwG;IACxG,OAAO,CAAC,EAAE,gBAAgB,CAAC,qBAAqB,CAAC,CAAA;CAClD,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,GAAG,EAAE,GAAG,CAAA;IACR,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,YAAY,KAAK,IAAI,CAAA;IACtC,KAAK,EAAE,CAAC,UAAU,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAA;IAC/C,KAAK,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAA;IACtC,aAAa,EAAE,CAAC,WAAW,EAAE,qBAAqB,EAAE,SAAS,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IAChF,UAAU,EAAE,UAAU,CAAA;CACvB,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAAI,wEASlC,2BAA2B,KAAG,cAiJhC,CAAA"}
{"version":3,"file":"create-api-client-modal.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/modal/helpers/create-api-client-modal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAY,MAAM,oBAAoB,CAAA;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,EAAE,KAAK,iBAAiB,EAA2B,MAAM,gCAAgC,CAAA;AAChG,OAAO,EAAE,KAAK,GAAG,EAAE,KAAK,gBAAgB,EAA6D,MAAM,KAAK,CAAA;AAEhH,OAAO,EAEL,KAAK,YAAY,EAElB,MAAM,sDAAsD,CAAA;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAuB,MAAM,oBAAoB,CAAA;AAI/E,KAAK,sBAAsB,GAAG;IAC5B,4CAA4C;IAC5C,EAAE,EAAE,WAAW,GAAG,IAAI,CAAA;IACtB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,kFAAkF;IAClF,QAAQ,CAAC,EAAE,iBAAiB,CAAA;IAC5B,6DAA6D;IAC7D,cAAc,EAAE,cAAc,CAAA;IAC9B,iDAAiD;IACjD,OAAO,CAAC,EAAE,YAAY,EAAE,CAAA;IACxB,wGAAwG;IACxG,OAAO,CAAC,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,CAAA;CAC7C,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,GAAG,EAAE,GAAG,CAAA;IACR,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,YAAY,KAAK,IAAI,CAAA;IACtC,KAAK,EAAE,CAAC,UAAU,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAA;IAC/C,KAAK,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAA;IACtC,aAAa,EAAE,CAAC,WAAW,EAAE,gBAAgB,EAAE,SAAS,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;IAC3E,UAAU,EAAE,UAAU,CAAA;CACvB,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAAI,wEASlC,sBAAsB,KAAG,cAiJ3B,CAAA"}

@@ -1,1 +0,1 @@

{"version":3,"file":"create-api-client-modal.js","names":[],"sources":["../../../../../src/v2/features/modal/helpers/create-api-client-modal.ts"],"sourcesContent":["import { type ModalState, useModal } from '@scalar/components'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport { type WorkspaceEventBus, createWorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { type App, type MaybeRefOrGetter, computed, createApp, isRef, reactive, ref, toValue, watch } from 'vue'\n\nimport {\n type DefaultEntities,\n type RoutePayload,\n resolveRouteParameters,\n} from '@/v2/features/modal/helpers/resolve-route-parameters'\nimport type { ApiClientModalOptions, ApiClientModalOptionsRef } from '@/v2/features/modal/helpers/types'\nimport { useModalSidebar } from '@/v2/features/modal/hooks/use-modal-sidebar'\nimport Modal, { type ModalProps } from '@/v2/features/modal/Modal.vue'\n\ntype CreateApiClientModalOptions = {\n /** Element to mount the client modal to. */\n el: HTMLElement | null\n /**\n * Will attempt to mount the references immediately.\n * For SSR this may need to be disabled and handled manually on the client side.\n */\n mountOnInitialize?: boolean\n /** You can pass in an event bus if you have one already, or we will create one */\n eventBus?: WorkspaceEventBus\n /** The workspace store must be initialized and passed in. */\n workspaceStore: WorkspaceStore\n /** Api client plugins to include in the modal */\n plugins?: ClientPlugin[]\n /** Subset of the configuration options for the modal, if you want it to be reactive ensure its a ref */\n options?: MaybeRefOrGetter<ApiClientModalOptions>\n}\n\nexport type ApiClientModal = {\n app: App\n open: (payload?: RoutePayload) => void\n mount: (mountingEl: HTMLElement | null) => void\n route: (payload: RoutePayload) => void\n updateOptions: (nextOptions: ApiClientModalOptions, overwrite?: boolean) => void\n modalState: ModalState\n}\n\n/**\n * Creates the API Client Modal.\n *\n * The modal does not require a router. Instead, navigation is handled by setting\n * active entities directly through the returned `route` function.\n */\nexport const createApiClientModal = ({\n el,\n eventBus = createWorkspaceEventBus({\n debug: import.meta.env.DEV,\n }),\n mountOnInitialize = true,\n plugins = [],\n workspaceStore,\n options = {},\n}: CreateApiClientModalOptions): ApiClientModal => {\n const requestBodyCompositionSelection = ref<Record<string, number>>({})\n\n /** This is to ensure that the options are a ref if they are not already, useful for react */\n const optionsRef = (isRef(options) ? options : ref(toValue(options))) as ApiClientModalOptionsRef\n\n const defaultEntities: DefaultEntities = {\n path: 'default',\n method: 'default',\n example: 'default',\n documentSlug: workspaceStore.workspace['x-scalar-active-document'] || 'default',\n }\n\n const parameters = reactive<DefaultEntities>({ ...defaultEntities })\n\n /** Navigate to the specified path, method, and example. */\n const route = (payload: RoutePayload): void => {\n Object.assign(parameters, defaultEntities, payload)\n }\n\n /** Resolved parameters from the workspace store. */\n const resolvedParameters = computed(() => resolveRouteParameters(workspaceStore, parameters))\n const documentSlug = computed(() => resolvedParameters.value.documentSlug)\n const path = computed(() => resolvedParameters.value.path)\n const method = computed(() => resolvedParameters.value.method)\n const exampleName = computed(() => resolvedParameters.value.example)\n /** The document from the workspace store. */\n const document = computed(() => workspaceStore.workspace.documents[documentSlug.value ?? ''] ?? null)\n\n /** Sidebar state and selection handling. */\n const sidebarState = useModalSidebar({\n workspaceStore,\n documentSlug: documentSlug,\n path: path,\n method: method,\n exampleName: exampleName,\n route,\n })\n\n const modalState = useModal()\n\n const app = createApp(Modal, {\n document,\n eventBus,\n exampleName,\n method,\n modalState,\n path,\n plugins,\n requestBodyCompositionSelection,\n sidebarState,\n workspaceStore,\n options: optionsRef,\n } satisfies ModalProps)\n\n /** Restore the workspace store when the modal is closed. */\n const handleModalClose = () => {\n requestBodyCompositionSelection.value = {}\n }\n\n /** Initialize plugins and subscribe to event bus events */\n const pluginUnsubscribes: (() => void)[] = []\n for (const plugin of plugins) {\n plugin.lifecycle?.onInit?.()\n\n if (plugin.on) {\n for (const [event, handler] of Object.entries(plugin.on)) {\n pluginUnsubscribes.push(eventBus.on(event as any, handler as any))\n }\n }\n }\n\n /** Clean up plugin lifecycle and event bus subscriptions when the app is unmounted */\n app.onUnmount(() => {\n for (const unsub of pluginUnsubscribes) {\n unsub()\n }\n for (const plugin of plugins) {\n plugin.lifecycle?.onDestroy?.()\n }\n })\n\n watch(\n () => modalState.open,\n (open) => (open ? null : handleModalClose()),\n )\n\n // Update the active proxy when the proxyUrl changes\n watch(\n () => toValue(optionsRef).proxyUrl,\n (newProxyUrl) => workspaceStore.update('x-scalar-active-proxy', newProxyUrl),\n { immediate: true },\n )\n\n // Use a unique id prefix to prevent collisions with other Vue apps on the page\n app.config.idPrefix = 'scalar-client'\n\n /** Mount the modal to a given element. */\n const mount = (mountingEl: HTMLElement | null = el): void => {\n if (!mountingEl) {\n console.error(\n '[@scalar/api-client] Could not create the API client Modal.',\n 'Invalid HTML element provided.',\n 'Read more: https://github.com/scalar/scalar/tree/main/packages/api-client',\n )\n return\n }\n app.mount(mountingEl)\n }\n\n if (mountOnInitialize) {\n mount()\n }\n\n return {\n /** The Vue app instance for the modal. Use with caution. */\n app,\n /** Open the modal and optionally navigate to a specific route. */\n open: (payload?: RoutePayload): void => {\n modalState.open = true\n if (payload) {\n route(payload)\n }\n },\n /** Mount the modal to a given element. */\n mount,\n /** Navigate to the specified path, method, and example. */\n route,\n /** Controls the visibility of the modal. */\n modalState,\n /**\n * Merge new options into the current modal options.\n *\n * @param newOptions - The new options to merge into the current modal options.\n * @param overwrite - Whether to overwrite the current modal options with the new options. If false, the new options will be merged with the current options.\n */\n updateOptions: (newOptions: ApiClientModalOptions, overwrite = false): void => {\n optionsRef.value = overwrite\n ? newOptions\n : {\n ...optionsRef.value,\n ...newOptions,\n }\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAgDA,IAAa,wBAAwB,EACnC,IACA,WAAW,wBAAwB,EACjC,OAAA,OACD,CAAC,EACF,oBAAoB,MACpB,UAAU,EAAE,EACZ,gBACA,UAAU,EAAE,OACqC;CACjD,MAAM,kCAAkC,IAA4B,EAAE,CAAC;;CAGvE,MAAM,aAAc,MAAM,QAAQ,GAAG,UAAU,IAAI,QAAQ,QAAQ,CAAC;CAEpE,MAAM,kBAAmC;EACvC,MAAM;EACN,QAAQ;EACR,SAAS;EACT,cAAc,eAAe,UAAU,+BAA+B;EACvE;CAED,MAAM,aAAa,SAA0B,EAAE,GAAG,iBAAiB,CAAC;;CAGpE,MAAM,SAAS,YAAgC;AAC7C,SAAO,OAAO,YAAY,iBAAiB,QAAQ;;;CAIrD,MAAM,qBAAqB,eAAe,uBAAuB,gBAAgB,WAAW,CAAC;CAC7F,MAAM,eAAe,eAAe,mBAAmB,MAAM,aAAa;CAC1E,MAAM,OAAO,eAAe,mBAAmB,MAAM,KAAK;CAC1D,MAAM,SAAS,eAAe,mBAAmB,MAAM,OAAO;CAC9D,MAAM,cAAc,eAAe,mBAAmB,MAAM,QAAQ;;CAEpE,MAAM,WAAW,eAAe,eAAe,UAAU,UAAU,aAAa,SAAS,OAAO,KAAK;;CAGrG,MAAM,eAAe,gBAAgB;EACnC;EACc;EACR;EACE;EACK;EACb;EACD,CAAC;CAEF,MAAM,aAAa,UAAU;CAE7B,MAAM,MAAM,UAAU,eAAO;EAC3B;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,SAAS;EACV,CAAsB;;CAGvB,MAAM,yBAAyB;AAC7B,kCAAgC,QAAQ,EAAE;;;CAI5C,MAAM,qBAAqC,EAAE;AAC7C,MAAK,MAAM,UAAU,SAAS;AAC5B,SAAO,WAAW,UAAU;AAE5B,MAAI,OAAO,GACT,MAAK,MAAM,CAAC,OAAO,YAAY,OAAO,QAAQ,OAAO,GAAG,CACtD,oBAAmB,KAAK,SAAS,GAAG,OAAc,QAAe,CAAC;;;AAMxE,KAAI,gBAAgB;AAClB,OAAK,MAAM,SAAS,mBAClB,QAAO;AAET,OAAK,MAAM,UAAU,QACnB,QAAO,WAAW,aAAa;GAEjC;AAEF,aACQ,WAAW,OAChB,SAAU,OAAO,OAAO,kBAAkB,CAC5C;AAGD,aACQ,QAAQ,WAAW,CAAC,WACzB,gBAAgB,eAAe,OAAO,yBAAyB,YAAY,EAC5E,EAAE,WAAW,MAAM,CACpB;AAGD,KAAI,OAAO,WAAW;;CAGtB,MAAM,SAAS,aAAiC,OAAa;AAC3D,MAAI,CAAC,YAAY;AACf,WAAQ,MACN,+DACA,kCACA,4EACD;AACD;;AAEF,MAAI,MAAM,WAAW;;AAGvB,KAAI,kBACF,QAAO;AAGT,QAAO;EAEL;EAEA,OAAO,YAAiC;AACtC,cAAW,OAAO;AAClB,OAAI,QACF,OAAM,QAAQ;;EAIlB;EAEA;EAEA;EAOA,gBAAgB,YAAmC,YAAY,UAAgB;AAC7E,cAAW,QAAQ,YACf,aACA;IACE,GAAG,WAAW;IACd,GAAG;IACJ;;EAER"}
{"version":3,"file":"create-api-client-modal.js","names":[],"sources":["../../../../../src/v2/features/modal/helpers/create-api-client-modal.ts"],"sourcesContent":["import { type ModalState, useModal } from '@scalar/components'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport { type WorkspaceEventBus, createWorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { type App, type MaybeRefOrGetter, computed, createApp, isRef, reactive, ref, toValue, watch } from 'vue'\n\nimport {\n type DefaultEntities,\n type RoutePayload,\n resolveRouteParameters,\n} from '@/v2/features/modal/helpers/resolve-route-parameters'\nimport type { ApiClientOptions, ApiClientOptionsRef } from '@/v2/types/options'\nimport { useModalSidebar } from '@/v2/features/modal/hooks/use-modal-sidebar'\nimport Modal, { type ModalProps } from '@/v2/features/modal/Modal.vue'\n\ntype CreateApiClientOptions = {\n /** Element to mount the client modal to. */\n el: HTMLElement | null\n /**\n * Will attempt to mount the references immediately.\n * For SSR this may need to be disabled and handled manually on the client side.\n */\n mountOnInitialize?: boolean\n /** You can pass in an event bus if you have one already, or we will create one */\n eventBus?: WorkspaceEventBus\n /** The workspace store must be initialized and passed in. */\n workspaceStore: WorkspaceStore\n /** Api client plugins to include in the modal */\n plugins?: ClientPlugin[]\n /** Subset of the configuration options for the modal, if you want it to be reactive ensure its a ref */\n options?: MaybeRefOrGetter<ApiClientOptions>\n}\n\nexport type ApiClientModal = {\n app: App\n open: (payload?: RoutePayload) => void\n mount: (mountingEl: HTMLElement | null) => void\n route: (payload: RoutePayload) => void\n updateOptions: (nextOptions: ApiClientOptions, overwrite?: boolean) => void\n modalState: ModalState\n}\n\n/**\n * Creates the API Client Modal.\n *\n * The modal does not require a router. Instead, navigation is handled by setting\n * active entities directly through the returned `route` function.\n */\nexport const createApiClientModal = ({\n el,\n eventBus = createWorkspaceEventBus({\n debug: import.meta.env.DEV,\n }),\n mountOnInitialize = true,\n plugins = [],\n workspaceStore,\n options = {},\n}: CreateApiClientOptions): ApiClientModal => {\n const requestBodyCompositionSelection = ref<Record<string, number>>({})\n\n /** This is to ensure that the options are a ref if they are not already, useful for react */\n const optionsRef = (isRef(options) ? options : ref(toValue(options))) as ApiClientOptionsRef\n\n const defaultEntities: DefaultEntities = {\n path: 'default',\n method: 'default',\n example: 'default',\n documentSlug: workspaceStore.workspace['x-scalar-active-document'] || 'default',\n }\n\n const parameters = reactive<DefaultEntities>({ ...defaultEntities })\n\n /** Navigate to the specified path, method, and example. */\n const route = (payload: RoutePayload): void => {\n Object.assign(parameters, defaultEntities, payload)\n }\n\n /** Resolved parameters from the workspace store. */\n const resolvedParameters = computed(() => resolveRouteParameters(workspaceStore, parameters))\n const documentSlug = computed(() => resolvedParameters.value.documentSlug)\n const path = computed(() => resolvedParameters.value.path)\n const method = computed(() => resolvedParameters.value.method)\n const exampleName = computed(() => resolvedParameters.value.example)\n /** The document from the workspace store. */\n const document = computed(() => workspaceStore.workspace.documents[documentSlug.value ?? ''] ?? null)\n\n /** Sidebar state and selection handling. */\n const sidebarState = useModalSidebar({\n workspaceStore,\n documentSlug: documentSlug,\n path: path,\n method: method,\n exampleName: exampleName,\n route,\n })\n\n const modalState = useModal()\n\n const app = createApp(Modal, {\n document,\n eventBus,\n exampleName,\n method,\n modalState,\n path,\n plugins,\n requestBodyCompositionSelection,\n sidebarState,\n workspaceStore,\n options: optionsRef,\n } satisfies ModalProps)\n\n /** Restore the workspace store when the modal is closed. */\n const handleModalClose = () => {\n requestBodyCompositionSelection.value = {}\n }\n\n /** Initialize plugins and subscribe to event bus events */\n const pluginUnsubscribes: (() => void)[] = []\n for (const plugin of plugins) {\n plugin.lifecycle?.onInit?.()\n\n if (plugin.on) {\n for (const [event, handler] of Object.entries(plugin.on)) {\n pluginUnsubscribes.push(eventBus.on(event as any, handler as any))\n }\n }\n }\n\n /** Clean up plugin lifecycle and event bus subscriptions when the app is unmounted */\n app.onUnmount(() => {\n for (const unsub of pluginUnsubscribes) {\n unsub()\n }\n for (const plugin of plugins) {\n plugin.lifecycle?.onDestroy?.()\n }\n })\n\n watch(\n () => modalState.open,\n (open) => (open ? null : handleModalClose()),\n )\n\n // Update the active proxy when the proxyUrl changes\n watch(\n () => toValue(optionsRef).proxyUrl,\n (newProxyUrl) => workspaceStore.update('x-scalar-active-proxy', newProxyUrl),\n { immediate: true },\n )\n\n // Use a unique id prefix to prevent collisions with other Vue apps on the page\n app.config.idPrefix = 'scalar-client'\n\n /** Mount the modal to a given element. */\n const mount = (mountingEl: HTMLElement | null = el): void => {\n if (!mountingEl) {\n console.error(\n '[@scalar/api-client] Could not create the API client Modal.',\n 'Invalid HTML element provided.',\n 'Read more: https://github.com/scalar/scalar/tree/main/packages/api-client',\n )\n return\n }\n app.mount(mountingEl)\n }\n\n if (mountOnInitialize) {\n mount()\n }\n\n return {\n /** The Vue app instance for the modal. Use with caution. */\n app,\n /** Open the modal and optionally navigate to a specific route. */\n open: (payload?: RoutePayload): void => {\n modalState.open = true\n if (payload) {\n route(payload)\n }\n },\n /** Mount the modal to a given element. */\n mount,\n /** Navigate to the specified path, method, and example. */\n route,\n /** Controls the visibility of the modal. */\n modalState,\n /**\n * Merge new options into the current modal options.\n *\n * @param newOptions - The new options to merge into the current modal options.\n * @param overwrite - Whether to overwrite the current modal options with the new options. If false, the new options will be merged with the current options.\n */\n updateOptions: (newOptions: ApiClientOptions, overwrite = false): void => {\n optionsRef.value = overwrite\n ? newOptions\n : {\n ...optionsRef.value,\n ...newOptions,\n }\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAgDA,IAAa,wBAAwB,EACnC,IACA,WAAW,wBAAwB,EACjC,OAAA,OACD,CAAC,EACF,oBAAoB,MACpB,UAAU,EAAE,EACZ,gBACA,UAAU,EAAE,OACgC;CAC5C,MAAM,kCAAkC,IAA4B,EAAE,CAAC;;CAGvE,MAAM,aAAc,MAAM,QAAQ,GAAG,UAAU,IAAI,QAAQ,QAAQ,CAAC;CAEpE,MAAM,kBAAmC;EACvC,MAAM;EACN,QAAQ;EACR,SAAS;EACT,cAAc,eAAe,UAAU,+BAA+B;EACvE;CAED,MAAM,aAAa,SAA0B,EAAE,GAAG,iBAAiB,CAAC;;CAGpE,MAAM,SAAS,YAAgC;AAC7C,SAAO,OAAO,YAAY,iBAAiB,QAAQ;;;CAIrD,MAAM,qBAAqB,eAAe,uBAAuB,gBAAgB,WAAW,CAAC;CAC7F,MAAM,eAAe,eAAe,mBAAmB,MAAM,aAAa;CAC1E,MAAM,OAAO,eAAe,mBAAmB,MAAM,KAAK;CAC1D,MAAM,SAAS,eAAe,mBAAmB,MAAM,OAAO;CAC9D,MAAM,cAAc,eAAe,mBAAmB,MAAM,QAAQ;;CAEpE,MAAM,WAAW,eAAe,eAAe,UAAU,UAAU,aAAa,SAAS,OAAO,KAAK;;CAGrG,MAAM,eAAe,gBAAgB;EACnC;EACc;EACR;EACE;EACK;EACb;EACD,CAAC;CAEF,MAAM,aAAa,UAAU;CAE7B,MAAM,MAAM,UAAU,eAAO;EAC3B;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,SAAS;EACV,CAAsB;;CAGvB,MAAM,yBAAyB;AAC7B,kCAAgC,QAAQ,EAAE;;;CAI5C,MAAM,qBAAqC,EAAE;AAC7C,MAAK,MAAM,UAAU,SAAS;AAC5B,SAAO,WAAW,UAAU;AAE5B,MAAI,OAAO,GACT,MAAK,MAAM,CAAC,OAAO,YAAY,OAAO,QAAQ,OAAO,GAAG,CACtD,oBAAmB,KAAK,SAAS,GAAG,OAAc,QAAe,CAAC;;;AAMxE,KAAI,gBAAgB;AAClB,OAAK,MAAM,SAAS,mBAClB,QAAO;AAET,OAAK,MAAM,UAAU,QACnB,QAAO,WAAW,aAAa;GAEjC;AAEF,aACQ,WAAW,OAChB,SAAU,OAAO,OAAO,kBAAkB,CAC5C;AAGD,aACQ,QAAQ,WAAW,CAAC,WACzB,gBAAgB,eAAe,OAAO,yBAAyB,YAAY,EAC5E,EAAE,WAAW,MAAM,CACpB;AAGD,KAAI,OAAO,WAAW;;CAGtB,MAAM,SAAS,aAAiC,OAAa;AAC3D,MAAI,CAAC,YAAY;AACf,WAAQ,MACN,+DACA,kCACA,4EACD;AACD;;AAEF,MAAI,MAAM,WAAW;;AAGvB,KAAI,kBACF,QAAO;AAGT,QAAO;EAEL;EAEA,OAAO,YAAiC;AACtC,cAAW,OAAO;AAClB,OAAI,QACF,OAAM,QAAQ;;EAIlB;EAEA;EAEA;EAOA,gBAAgB,YAA8B,YAAY,UAAgB;AACxE,cAAW,QAAQ,YACf,aACA;IACE,GAAG,WAAW;IACd,GAAG;IACJ;;EAER"}

@@ -1,8 +0,2 @@

import type { ApiReferenceConfigurationRaw } from '@scalar/types/api-reference';
import type { Ref } from 'vue';
/**
* Configuration options supported by the API Client modal constructor.
*/
export type ApiClientModalOptions = Partial<Pick<ApiReferenceConfigurationRaw, 'authentication' | 'baseServerURL' | 'hideClientButton' | 'hiddenClients' | 'oauth2RedirectUri' | 'proxyUrl' | 'servers'>>;
export type ApiClientModalOptionsRef = Ref<ApiClientModalOptions>;
export type { ApiClientOptions, ApiClientOptionsRef } from '../../../../v2/types/options';
//# sourceMappingURL=types.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/modal/helpers/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,6BAA6B,CAAA;AAC/E,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAE9B;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,OAAO,CACzC,IAAI,CACF,4BAA4B,EAC1B,gBAAgB,GAChB,eAAe,GACf,kBAAkB,GAClB,eAAe,GACf,mBAAmB,GACnB,UAAU,GACV,SAAS,CACZ,CACF,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG,GAAG,CAAC,qBAAqB,CAAC,CAAA"}
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/modal/helpers/types.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA"}
export { type ApiClientModal, createApiClientModal } from './helpers/create-api-client-modal.js';
export { mapHiddenClientsConfig } from './helpers/map-hidden-clients-config.js';
export type { RoutePayload } from './helpers/resolve-route-parameters.js';
export type { ApiClientModalOptions } from './helpers/types';
export type { ApiClientOptions } from '../../../v2/types/options';
export { initializeModalEvents } from './modal-events.js';
//# sourceMappingURL=index.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/v2/features/modal/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAA;AAC7F,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAA;AAC5E,YAAY,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AACtE,YAAY,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAA"}
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/v2/features/modal/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,cAAc,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAA;AAC7F,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAA;AAC5E,YAAY,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAA;AACtE,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAA"}
import { type ModalState } from '@scalar/components';
import type { HttpMethod } from '@scalar/helpers/http/http-methods';
import type { ClientPlugin } from '@scalar/oas-utils/helpers';
import type { ApiReferenceConfigurationRaw } from '@scalar/types/api-reference';
import type { WorkspaceStore } from '@scalar/workspace-store/client';
import { type WorkspaceEventBus } from '@scalar/workspace-store/events';
import type { WorkspaceDocument } from '@scalar/workspace-store/schemas';
import { type ComputedRef, type MaybeRefOrGetter, type Ref } from 'vue';
import type { ApiClientModalOptionsRef } from '../../../v2/features/modal/helpers/types';
import { type ComputedRef, type Ref } from 'vue';
import { type UseModalSidebarReturn } from '../../../v2/features/modal/hooks/use-modal-sidebar.js';
import type { ApiClientOptionsRef } from '../../../v2/types/options';
import type { MaybeRefOrGetter } from 'vue';
import type { ApiClientOptions } from '../../../v2/types/options';
export type ModalProps = {

@@ -33,3 +34,3 @@ /** The workspace store must be initialized and passed in */

/** Subset of the configuration options for the modal */
options: MaybeRefOrGetter<Partial<Pick<ApiReferenceConfigurationRaw, 'authentication' | 'baseServerURL' | 'hideClientButton' | 'hiddenClients' | 'oauth2RedirectUri' | 'servers'>>>;
options: MaybeRefOrGetter<ApiClientOptions>;
};

@@ -44,3 +45,3 @@ /**

declare const __VLS_export: import("vue").DefineComponent<Omit<ModalProps, "options"> & {
options: ApiClientModalOptionsRef;
options: ApiClientOptionsRef;
}, {

@@ -50,4 +51,4 @@ sidebarWidth: ComputedRef<number>;

}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Omit<ModalProps, "options"> & {
options: ApiClientModalOptionsRef;
options: ApiClientOptionsRef;
}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
//# sourceMappingURL=Modal.vue.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"Modal.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/features/modal/Modal.vue"],"names":[],"mappings":"AAyNA,OAAO,EAAE,KAAK,UAAU,EAA4B,MAAM,oBAAoB,CAAA;AAC9E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAC7D,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,6BAA6B,CAAA;AAE/E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAEvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACxE,OAAO,EAKL,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,GAAG,EACT,MAAM,KAAK,CAAA;AAIZ,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAA;AACjF,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,6CAA6C,CAAA;AAOxF,MAAM,MAAM,UAAU,GAAG;IACvB,4DAA4D;IAC5D,cAAc,EAAE,cAAc,CAAA;IAC9B,qDAAqD;IACrD,QAAQ,EAAE,WAAW,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAA;IAC/C,iDAAiD;IACjD,IAAI,EAAE,WAAW,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IACrC,4CAA4C;IAC5C,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,mDAAmD;IACnD,MAAM,EAAE,WAAW,CAAC,UAAU,GAAG,SAAS,CAAC,CAAA;IAC3C,yDAAyD;IACzD,WAAW,EAAE,WAAW,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IAC5C,sEAAsE;IACtE,+BAA+B,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAC5D,2CAA2C;IAC3C,UAAU,EAAE,UAAU,CAAA;IACtB,0DAA0D;IAC1D,YAAY,EAAE,qBAAqB,CAAA;IACnC,iDAAiD;IACjD,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,wDAAwD;IACxD,OAAO,EAAE,gBAAgB,CACvB,OAAO,CACL,IAAI,CACF,4BAA4B,EAC1B,gBAAgB,GAChB,eAAe,GACf,kBAAkB,GAClB,eAAe,GACf,mBAAmB,GACnB,SAAS,CACZ,CACF,CACF,CAAA;CACF,CAAA;AAED;;;;GAIG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;aAC0C,wBAAwB;;;;;aAAxB,wBAAwB;iGAwQhF,CAAC"}
{"version":3,"file":"Modal.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/features/modal/Modal.vue"],"names":[],"mappings":"AA+MA,OAAO,EAAE,KAAK,UAAU,EAA4B,MAAM,oBAAoB,CAAA;AAC9E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAA;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAE7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAEvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACxE,OAAO,EAKL,KAAK,WAAW,EAChB,KAAK,GAAG,EACT,MAAM,KAAK,CAAA;AAIZ,OAAO,EAAE,KAAK,qBAAqB,EAAE,MAAM,6CAA6C,CAAA;AAKxF,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAG7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,KAAK,CAAA;AAE3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAE1D,MAAM,MAAM,UAAU,GAAG;IACvB,4DAA4D;IAC5D,cAAc,EAAE,cAAc,CAAA;IAC9B,qDAAqD;IACrD,QAAQ,EAAE,WAAW,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAA;IAC/C,iDAAiD;IACjD,IAAI,EAAE,WAAW,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IACrC,4CAA4C;IAC5C,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,mDAAmD;IACnD,MAAM,EAAE,WAAW,CAAC,UAAU,GAAG,SAAS,CAAC,CAAA;IAC3C,yDAAyD;IACzD,WAAW,EAAE,WAAW,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IAC5C,sEAAsE;IACtE,+BAA+B,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAC5D,2CAA2C;IAC3C,UAAU,EAAE,UAAU,CAAA;IACtB,0DAA0D;IAC1D,YAAY,EAAE,qBAAqB,CAAA;IACnC,iDAAiD;IACjD,OAAO,EAAE,YAAY,EAAE,CAAA;IACvB,wDAAwD;IACxD,OAAO,EAAE,gBAAgB,CAAC,gBAAgB,CAAC,CAAA;CAC5C,CAAA;AAED;;;;GAIG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;aAC0C,mBAAmB;;;;;aAAnB,mBAAmB;iGAwQ3E,CAAC"}

@@ -1,1 +0,1 @@

{"version":3,"file":"Modal.vue.js","names":[],"sources":["../../../../src/v2/features/modal/Modal.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type ModalProps = {\n /** The workspace store must be initialized and passed in */\n workspaceStore: WorkspaceStore\n /** The document must be initialized and passed in */\n document: ComputedRef<WorkspaceDocument | null>\n /** The path must be initialized and passed in */\n path: ComputedRef<string | undefined>\n /** The event bus for handling all events */\n eventBus: WorkspaceEventBus\n /** The method must be initialized and passed in */\n method: ComputedRef<HttpMethod | undefined>\n /** The example name must be initialized and passed in */\n exampleName: ComputedRef<string | undefined>\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection: Ref<Record<string, number>>\n /** Controls the visibility of the modal */\n modalState: ModalState\n /** The sidebar state must be initialized and passed in */\n sidebarState: UseModalSidebarReturn\n /** Api client plugins to include in the modal */\n plugins: ClientPlugin[]\n /** Subset of the configuration options for the modal */\n options: MaybeRefOrGetter<\n Partial<\n Pick<\n ApiReferenceConfigurationRaw,\n | 'authentication'\n | 'baseServerURL'\n | 'hideClientButton'\n | 'hiddenClients'\n | 'oauth2RedirectUri'\n | 'servers'\n >\n >\n >\n}\n\n/**\n * Scalar Api Client Modal\n *\n * This component is used to render the API Client Modal\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { type ModalState, type ScalarListboxOption } from '@scalar/components'\nimport type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport type { ApiReferenceConfigurationRaw } from '@scalar/types/api-reference'\nimport { ScalarToasts } from '@scalar/use-toasts'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport { type WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getActiveEnvironment } from '@scalar/workspace-store/request-example'\nimport type { WorkspaceDocument } from '@scalar/workspace-store/schemas'\nimport {\n computed,\n onBeforeUnmount,\n ref,\n watch,\n type ComputedRef,\n type MaybeRefOrGetter,\n type Ref,\n} from 'vue'\n\nimport ModalClientContainer from '@/v2/components/modals/ModalClientContainer.vue'\nimport { Sidebar, SidebarToggle } from '@/v2/components/sidebar'\nimport type { ApiClientModalOptionsRef } from '@/v2/features/modal/helpers/types'\nimport { type UseModalSidebarReturn } from '@/v2/features/modal/hooks/use-modal-sidebar'\nimport { initializeModalEvents } from '@/v2/features/modal/modal-events'\nimport Operation from '@/v2/features/operation/Operation.vue'\nimport { useGlobalHotKeys } from '@/v2/hooks/use-global-hot-keys'\nimport { useScrollLock } from '@/v2/hooks/use-scroll-lock'\n\nconst {\n document,\n eventBus,\n modalState,\n options,\n plugins,\n requestBodyCompositionSelection,\n sidebarState,\n workspaceStore,\n} = defineProps<\n Omit<ModalProps, 'options'> & { options: ApiClientModalOptionsRef }\n>()\n\nconst activeWorkspace: ScalarListboxOption = {\n label: 'default',\n id: 'default',\n}\n\n/** Controls the visibility of the sidebar. */\nconst isSidebarOpen = ref(false)\n\n/** Initialize modal events */\ninitializeModalEvents({\n eventBus,\n isSidebarOpen,\n requestBodyCompositionSelection,\n sidebarState,\n modalState,\n store: workspaceStore,\n})\n\n/** Register global hotkeys for the app, passing the workspace event bus and layout state */\nuseGlobalHotKeys(eventBus, 'modal', () => !modalState.open)\n\n/** Clean up on close */\nconst cleanUp = () => {\n eventBus.emit('operation:cancel:request')\n}\n\nconst isLocked = useScrollLock(() => {\n if (typeof window !== 'undefined') {\n return window.document.body\n }\n return null\n})\n\nwatch(\n () => modalState.open,\n (open) => {\n // Make sure scrolling is locked or unlocked when the modal is opened or closed\n isLocked.value = open\n\n if (!open) {\n cleanUp()\n }\n },\n)\n\n// Ensure we add our scalar wrapper class to the headless ui root\nonBeforeUnmount(() => cleanUp())\n\n/** Default sidebar width in pixels. */\nconst DEFAULT_SIDEBAR_WIDTH = 288\n\n/** Width of the sidebar, with fallback to default. */\nconst sidebarWidth = computed(\n () =>\n workspaceStore?.workspace?.['x-scalar-sidebar-width'] ??\n DEFAULT_SIDEBAR_WIDTH,\n)\n\n/** Handler for sidebar width changes. */\nconst handleSidebarWidthUpdate = (width: number) =>\n workspaceStore?.update('x-scalar-sidebar-width', width)\n\n/**\n * Merged environment variables from workspace and document levels.\n * Variables from both sources are combined, with document variables\n * taking precedence in case of naming conflicts.\n */\nconst environment = computed(\n () => getActiveEnvironment(workspaceStore, document.value).environment,\n)\n\ndefineExpose({\n sidebarWidth,\n environment,\n})\n</script>\n\n<template>\n <ModalClientContainer :modalState>\n <!-- Toasts -->\n <ScalarToasts />\n\n <!-- If we have a document, path and method, render the operation -->\n <main\n v-if=\"document.value && path?.value && method?.value\"\n class=\"relative flex h-full min-h-0 w-full flex-1\">\n <SidebarToggle\n v-model=\"isSidebarOpen\"\n class=\"absolute top-2 left-3 z-2\" />\n <Sidebar\n v-show=\"isSidebarOpen\"\n v-model:sidebarWidth=\"sidebarWidth\"\n :activeWorkspace=\"activeWorkspace\"\n class=\"h-full max-md:absolute! max-md:w-full!\"\n :documents=\"[document.value]\"\n :eventBus\n :isDroppable=\"() => false\"\n layout=\"modal\"\n :sidebarState=\"sidebarState.state\"\n :workspaces=\"[]\"\n @selectItem=\"sidebarState.handleSelectItem\"\n @update:sidebarWidth=\"handleSidebarWidthUpdate\" />\n <Operation\n :activeWorkspace=\"activeWorkspace\"\n class=\"flex-1\"\n :document=\"document.value\"\n :documentSlug=\"document.value['x-scalar-navigation']?.id ?? ''\"\n :environment\n :eventBus\n :exampleName=\"exampleName?.value\"\n layout=\"modal\"\n :method=\"method?.value\"\n :options\n :path=\"path?.value\"\n :plugins\n :requestBodyCompositionSelection=\"requestBodyCompositionSelection.value\"\n :workspaceStore />\n </main>\n <!-- Empty state -->\n <div\n v-else\n class=\"flex h-full w-full items-center justify-center\">\n <span class=\"text-c-3\">No document selected</span>\n </div>\n </ModalClientContainer>\n</template>\n"],"mappings":""}
{"version":3,"file":"Modal.vue.js","names":[],"sources":["../../../../src/v2/features/modal/Modal.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { MaybeRefOrGetter } from 'vue'\n\nimport type { ApiClientOptions } from '@/v2/types/options'\n\nexport type ModalProps = {\n /** The workspace store must be initialized and passed in */\n workspaceStore: WorkspaceStore\n /** The document must be initialized and passed in */\n document: ComputedRef<WorkspaceDocument | null>\n /** The path must be initialized and passed in */\n path: ComputedRef<string | undefined>\n /** The event bus for handling all events */\n eventBus: WorkspaceEventBus\n /** The method must be initialized and passed in */\n method: ComputedRef<HttpMethod | undefined>\n /** The example name must be initialized and passed in */\n exampleName: ComputedRef<string | undefined>\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection: Ref<Record<string, number>>\n /** Controls the visibility of the modal */\n modalState: ModalState\n /** The sidebar state must be initialized and passed in */\n sidebarState: UseModalSidebarReturn\n /** Api client plugins to include in the modal */\n plugins: ClientPlugin[]\n /** Subset of the configuration options for the modal */\n options: MaybeRefOrGetter<ApiClientOptions>\n}\n\n/**\n * Scalar Api Client Modal\n *\n * This component is used to render the API Client Modal\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { type ModalState, type ScalarListboxOption } from '@scalar/components'\nimport type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport { ScalarToasts } from '@scalar/use-toasts'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport { type WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getActiveEnvironment } from '@scalar/workspace-store/request-example'\nimport type { WorkspaceDocument } from '@scalar/workspace-store/schemas'\nimport {\n computed,\n onBeforeUnmount,\n ref,\n watch,\n type ComputedRef,\n type Ref,\n} from 'vue'\n\nimport ModalClientContainer from '@/v2/components/modals/ModalClientContainer.vue'\nimport { Sidebar, SidebarToggle } from '@/v2/components/sidebar'\nimport { type UseModalSidebarReturn } from '@/v2/features/modal/hooks/use-modal-sidebar'\nimport { initializeModalEvents } from '@/v2/features/modal/modal-events'\nimport Operation from '@/v2/features/operation/Operation.vue'\nimport { useGlobalHotKeys } from '@/v2/hooks/use-global-hot-keys'\nimport { useScrollLock } from '@/v2/hooks/use-scroll-lock'\nimport type { ApiClientOptionsRef } from '@/v2/types/options'\n\nconst {\n document,\n eventBus,\n modalState,\n options,\n plugins,\n requestBodyCompositionSelection,\n sidebarState,\n workspaceStore,\n} = defineProps<\n Omit<ModalProps, 'options'> & { options: ApiClientOptionsRef }\n>()\n\nconst activeWorkspace: ScalarListboxOption = {\n label: 'default',\n id: 'default',\n}\n\n/** Controls the visibility of the sidebar. */\nconst isSidebarOpen = ref(false)\n\n/** Initialize modal events */\ninitializeModalEvents({\n eventBus,\n isSidebarOpen,\n requestBodyCompositionSelection,\n sidebarState,\n modalState,\n store: workspaceStore,\n})\n\n/** Register global hotkeys for the app, passing the workspace event bus and layout state */\nuseGlobalHotKeys(eventBus, 'modal', () => !modalState.open)\n\n/** Clean up on close */\nconst cleanUp = () => {\n eventBus.emit('operation:cancel:request')\n}\n\nconst isLocked = useScrollLock(() => {\n if (typeof window !== 'undefined') {\n return window.document.body\n }\n return null\n})\n\nwatch(\n () => modalState.open,\n (open) => {\n // Make sure scrolling is locked or unlocked when the modal is opened or closed\n isLocked.value = open\n\n if (!open) {\n cleanUp()\n }\n },\n)\n\n// Ensure we add our scalar wrapper class to the headless ui root\nonBeforeUnmount(() => cleanUp())\n\n/** Default sidebar width in pixels. */\nconst DEFAULT_SIDEBAR_WIDTH = 288\n\n/** Width of the sidebar, with fallback to default. */\nconst sidebarWidth = computed(\n () =>\n workspaceStore?.workspace?.['x-scalar-sidebar-width'] ??\n DEFAULT_SIDEBAR_WIDTH,\n)\n\n/** Handler for sidebar width changes. */\nconst handleSidebarWidthUpdate = (width: number) =>\n workspaceStore?.update('x-scalar-sidebar-width', width)\n\n/**\n * Merged environment variables from workspace and document levels.\n * Variables from both sources are combined, with document variables\n * taking precedence in case of naming conflicts.\n */\nconst environment = computed(\n () => getActiveEnvironment(workspaceStore, document.value).environment,\n)\n\ndefineExpose({\n sidebarWidth,\n environment,\n})\n</script>\n\n<template>\n <ModalClientContainer :modalState>\n <!-- Toasts -->\n <ScalarToasts />\n\n <!-- If we have a document, path and method, render the operation -->\n <main\n v-if=\"document.value && path?.value && method?.value\"\n class=\"relative flex h-full min-h-0 w-full flex-1\">\n <SidebarToggle\n v-model=\"isSidebarOpen\"\n class=\"absolute top-2 left-3 z-2\" />\n <Sidebar\n v-show=\"isSidebarOpen\"\n v-model:sidebarWidth=\"sidebarWidth\"\n :activeWorkspace=\"activeWorkspace\"\n class=\"h-full max-md:absolute! max-md:w-full!\"\n :documents=\"[document.value]\"\n :eventBus\n :isDroppable=\"() => false\"\n layout=\"modal\"\n :sidebarState=\"sidebarState.state\"\n :workspaces=\"[]\"\n @selectItem=\"sidebarState.handleSelectItem\"\n @update:sidebarWidth=\"handleSidebarWidthUpdate\" />\n <Operation\n :activeWorkspace=\"activeWorkspace\"\n class=\"flex-1\"\n :document=\"document.value\"\n :documentSlug=\"document.value['x-scalar-navigation']?.id ?? ''\"\n :environment\n :eventBus\n :exampleName=\"exampleName?.value\"\n layout=\"modal\"\n :method=\"method?.value\"\n :options\n :path=\"path?.value\"\n :plugins\n :requestBodyCompositionSelection=\"requestBodyCompositionSelection.value\"\n :workspaceStore />\n </main>\n <!-- Empty state -->\n <div\n v-else\n class=\"flex h-full w-full items-center justify-center\">\n <span class=\"text-c-3\">No document selected</span>\n </div>\n </ModalClientContainer>\n</template>\n"],"mappings":""}

@@ -1,1 +0,1 @@

{"version":3,"file":"Modal.vue.script.js","names":[],"sources":["../../../../src/v2/features/modal/Modal.vue"],"sourcesContent":["<script lang=\"ts\">\nexport type ModalProps = {\n /** The workspace store must be initialized and passed in */\n workspaceStore: WorkspaceStore\n /** The document must be initialized and passed in */\n document: ComputedRef<WorkspaceDocument | null>\n /** The path must be initialized and passed in */\n path: ComputedRef<string | undefined>\n /** The event bus for handling all events */\n eventBus: WorkspaceEventBus\n /** The method must be initialized and passed in */\n method: ComputedRef<HttpMethod | undefined>\n /** The example name must be initialized and passed in */\n exampleName: ComputedRef<string | undefined>\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection: Ref<Record<string, number>>\n /** Controls the visibility of the modal */\n modalState: ModalState\n /** The sidebar state must be initialized and passed in */\n sidebarState: UseModalSidebarReturn\n /** Api client plugins to include in the modal */\n plugins: ClientPlugin[]\n /** Subset of the configuration options for the modal */\n options: MaybeRefOrGetter<\n Partial<\n Pick<\n ApiReferenceConfigurationRaw,\n | 'authentication'\n | 'baseServerURL'\n | 'hideClientButton'\n | 'hiddenClients'\n | 'oauth2RedirectUri'\n | 'servers'\n >\n >\n >\n}\n\n/**\n * Scalar Api Client Modal\n *\n * This component is used to render the API Client Modal\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { type ModalState, type ScalarListboxOption } from '@scalar/components'\nimport type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport type { ApiReferenceConfigurationRaw } from '@scalar/types/api-reference'\nimport { ScalarToasts } from '@scalar/use-toasts'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport { type WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getActiveEnvironment } from '@scalar/workspace-store/request-example'\nimport type { WorkspaceDocument } from '@scalar/workspace-store/schemas'\nimport {\n computed,\n onBeforeUnmount,\n ref,\n watch,\n type ComputedRef,\n type MaybeRefOrGetter,\n type Ref,\n} from 'vue'\n\nimport ModalClientContainer from '@/v2/components/modals/ModalClientContainer.vue'\nimport { Sidebar, SidebarToggle } from '@/v2/components/sidebar'\nimport type { ApiClientModalOptionsRef } from '@/v2/features/modal/helpers/types'\nimport { type UseModalSidebarReturn } from '@/v2/features/modal/hooks/use-modal-sidebar'\nimport { initializeModalEvents } from '@/v2/features/modal/modal-events'\nimport Operation from '@/v2/features/operation/Operation.vue'\nimport { useGlobalHotKeys } from '@/v2/hooks/use-global-hot-keys'\nimport { useScrollLock } from '@/v2/hooks/use-scroll-lock'\n\nconst {\n document,\n eventBus,\n modalState,\n options,\n plugins,\n requestBodyCompositionSelection,\n sidebarState,\n workspaceStore,\n} = defineProps<\n Omit<ModalProps, 'options'> & { options: ApiClientModalOptionsRef }\n>()\n\nconst activeWorkspace: ScalarListboxOption = {\n label: 'default',\n id: 'default',\n}\n\n/** Controls the visibility of the sidebar. */\nconst isSidebarOpen = ref(false)\n\n/** Initialize modal events */\ninitializeModalEvents({\n eventBus,\n isSidebarOpen,\n requestBodyCompositionSelection,\n sidebarState,\n modalState,\n store: workspaceStore,\n})\n\n/** Register global hotkeys for the app, passing the workspace event bus and layout state */\nuseGlobalHotKeys(eventBus, 'modal', () => !modalState.open)\n\n/** Clean up on close */\nconst cleanUp = () => {\n eventBus.emit('operation:cancel:request')\n}\n\nconst isLocked = useScrollLock(() => {\n if (typeof window !== 'undefined') {\n return window.document.body\n }\n return null\n})\n\nwatch(\n () => modalState.open,\n (open) => {\n // Make sure scrolling is locked or unlocked when the modal is opened or closed\n isLocked.value = open\n\n if (!open) {\n cleanUp()\n }\n },\n)\n\n// Ensure we add our scalar wrapper class to the headless ui root\nonBeforeUnmount(() => cleanUp())\n\n/** Default sidebar width in pixels. */\nconst DEFAULT_SIDEBAR_WIDTH = 288\n\n/** Width of the sidebar, with fallback to default. */\nconst sidebarWidth = computed(\n () =>\n workspaceStore?.workspace?.['x-scalar-sidebar-width'] ??\n DEFAULT_SIDEBAR_WIDTH,\n)\n\n/** Handler for sidebar width changes. */\nconst handleSidebarWidthUpdate = (width: number) =>\n workspaceStore?.update('x-scalar-sidebar-width', width)\n\n/**\n * Merged environment variables from workspace and document levels.\n * Variables from both sources are combined, with document variables\n * taking precedence in case of naming conflicts.\n */\nconst environment = computed(\n () => getActiveEnvironment(workspaceStore, document.value).environment,\n)\n\ndefineExpose({\n sidebarWidth,\n environment,\n})\n</script>\n\n<template>\n <ModalClientContainer :modalState>\n <!-- Toasts -->\n <ScalarToasts />\n\n <!-- If we have a document, path and method, render the operation -->\n <main\n v-if=\"document.value && path?.value && method?.value\"\n class=\"relative flex h-full min-h-0 w-full flex-1\">\n <SidebarToggle\n v-model=\"isSidebarOpen\"\n class=\"absolute top-2 left-3 z-2\" />\n <Sidebar\n v-show=\"isSidebarOpen\"\n v-model:sidebarWidth=\"sidebarWidth\"\n :activeWorkspace=\"activeWorkspace\"\n class=\"h-full max-md:absolute! max-md:w-full!\"\n :documents=\"[document.value]\"\n :eventBus\n :isDroppable=\"() => false\"\n layout=\"modal\"\n :sidebarState=\"sidebarState.state\"\n :workspaces=\"[]\"\n @selectItem=\"sidebarState.handleSelectItem\"\n @update:sidebarWidth=\"handleSidebarWidthUpdate\" />\n <Operation\n :activeWorkspace=\"activeWorkspace\"\n class=\"flex-1\"\n :document=\"document.value\"\n :documentSlug=\"document.value['x-scalar-navigation']?.id ?? ''\"\n :environment\n :eventBus\n :exampleName=\"exampleName?.value\"\n layout=\"modal\"\n :method=\"method?.value\"\n :options\n :path=\"path?.value\"\n :plugins\n :requestBodyCompositionSelection=\"requestBodyCompositionSelection.value\"\n :workspaceStore />\n </main>\n <!-- Empty state -->\n <div\n v-else\n class=\"flex h-full w-full items-center justify-center\">\n <span class=\"text-c-3\">No document selected</span>\n </div>\n </ModalClientContainer>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwFA,MAAM,kBAAuC;GAC3C,OAAO;GACP,IAAI;GACN;;EAGA,MAAM,gBAAgB,IAAI,MAAK;;AAG/B,wBAAsB;GACpB,UAAO,QAAA;GACP;GACA,iCAA8B,QAAA;GAC9B,cAAW,QAAA;GACX,YAAS,QAAA;GACT,OAAO,QAAA;GACR,CAAA;;AAGD,mBAAiB,QAAA,UAAU,eAAe,CAAC,QAAA,WAAW,KAAI;;EAG1D,MAAM,gBAAgB;AACpB,WAAA,SAAS,KAAK,2BAA0B;;EAG1C,MAAM,WAAW,oBAAoB;AACnC,OAAI,OAAO,WAAW,YACpB,QAAO,OAAO,SAAS;AAEzB,UAAO;IACR;AAED,cACQ,QAAA,WAAW,OAChB,SAAS;AAER,YAAS,QAAQ;AAEjB,OAAI,CAAC,KACH,UAAQ;IAGd;AAGA,wBAAsB,SAAS,CAAA;;EAG/B,MAAM,wBAAwB;;EAG9B,MAAM,eAAe,eAEjB,QAAA,gBAAgB,YAAY,6BAC5B,sBACJ;;EAGA,MAAM,4BAA4B,UAChC,QAAA,gBAAgB,OAAO,0BAA0B,MAAK;;;;;;EAOxD,MAAM,cAAc,eACZ,qBAAqB,QAAA,gBAAgB,QAAA,SAAS,MAAM,CAAC,YAC7D;AAEA,WAAa;GACX;GACA;GACD,CAAA;;uBAIC,YA8CuB,8BAAA,EA9CA,YAAA,QAAA,YAAU,EAAA;2BAEf,CAAhB,YAAgB,MAAA,aAAA,CAAA,EAIR,QAAA,SAAS,SAAS,QAAA,MAAM,SAAS,QAAA,QAAQ,SAAA,WAAA,EADjD,mBAkCO,QAlCP,YAkCO;KA/BL,YAEsC,MAAA,sBAAA,EAAA;kBAD3B,cAAA;iFAAa,QAAA;MACtB,OAAM;;oBACR,YAYoD,MAAA,gBAAA,EAAA;MAV1C,cAAc,aAAA;mFAAY,QAAA,SAUZ,yBAAA;MATJ;MAClB,OAAM;MACL,WAAS,CAAG,QAAA,SAAS,MAAK;MAC1B,UAAA,QAAA;MACA,mBAAa;MACd,QAAO;MACN,cAAc,QAAA,aAAa;MAC3B,YAAY,EAAE;MACd,cAAY,QAAA,aAAa;;;;;;;kBAVlB,cAAA,MAAa,CAAA,CAAA;KAYvB,YAcoB,mBAAA;MAbA;MAClB,OAAM;MACL,UAAU,QAAA,SAAS;MACnB,cAAc,QAAA,SAAS,MAAK,wBAAyB,MAAE;MACvD,aAAA,YAAA;MACA,UAAA,QAAA;MACA,aAAa,QAAA,aAAa;MAC3B,QAAO;MACN,QAAQ,QAAA,QAAQ;MAChB,SAAA,QAAA;MACA,MAAM,QAAA,MAAM;MACZ,SAAA,QAAA;MACA,iCAAiC,QAAA,gCAAgC;MACjE,gBAAA,QAAA;;;;;;;;;;;;;;wBAGL,mBAIM,OAJN,YAIM,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CADJ,mBAAkD,QAAA,EAA5C,OAAM,YAAU,EAAC,wBAAoB,GAAA,CAAA,EAAA,CAAA,EAAA,CAAA"}
{"version":3,"file":"Modal.vue.script.js","names":[],"sources":["../../../../src/v2/features/modal/Modal.vue"],"sourcesContent":["<script lang=\"ts\">\nimport type { MaybeRefOrGetter } from 'vue'\n\nimport type { ApiClientOptions } from '@/v2/types/options'\n\nexport type ModalProps = {\n /** The workspace store must be initialized and passed in */\n workspaceStore: WorkspaceStore\n /** The document must be initialized and passed in */\n document: ComputedRef<WorkspaceDocument | null>\n /** The path must be initialized and passed in */\n path: ComputedRef<string | undefined>\n /** The event bus for handling all events */\n eventBus: WorkspaceEventBus\n /** The method must be initialized and passed in */\n method: ComputedRef<HttpMethod | undefined>\n /** The example name must be initialized and passed in */\n exampleName: ComputedRef<string | undefined>\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection: Ref<Record<string, number>>\n /** Controls the visibility of the modal */\n modalState: ModalState\n /** The sidebar state must be initialized and passed in */\n sidebarState: UseModalSidebarReturn\n /** Api client plugins to include in the modal */\n plugins: ClientPlugin[]\n /** Subset of the configuration options for the modal */\n options: MaybeRefOrGetter<ApiClientOptions>\n}\n\n/**\n * Scalar Api Client Modal\n *\n * This component is used to render the API Client Modal\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { type ModalState, type ScalarListboxOption } from '@scalar/components'\nimport type { HttpMethod } from '@scalar/helpers/http/http-methods'\nimport type { ClientPlugin } from '@scalar/oas-utils/helpers'\nimport { ScalarToasts } from '@scalar/use-toasts'\nimport type { WorkspaceStore } from '@scalar/workspace-store/client'\nimport { type WorkspaceEventBus } from '@scalar/workspace-store/events'\nimport { getActiveEnvironment } from '@scalar/workspace-store/request-example'\nimport type { WorkspaceDocument } from '@scalar/workspace-store/schemas'\nimport {\n computed,\n onBeforeUnmount,\n ref,\n watch,\n type ComputedRef,\n type Ref,\n} from 'vue'\n\nimport ModalClientContainer from '@/v2/components/modals/ModalClientContainer.vue'\nimport { Sidebar, SidebarToggle } from '@/v2/components/sidebar'\nimport { type UseModalSidebarReturn } from '@/v2/features/modal/hooks/use-modal-sidebar'\nimport { initializeModalEvents } from '@/v2/features/modal/modal-events'\nimport Operation from '@/v2/features/operation/Operation.vue'\nimport { useGlobalHotKeys } from '@/v2/hooks/use-global-hot-keys'\nimport { useScrollLock } from '@/v2/hooks/use-scroll-lock'\nimport type { ApiClientOptionsRef } from '@/v2/types/options'\n\nconst {\n document,\n eventBus,\n modalState,\n options,\n plugins,\n requestBodyCompositionSelection,\n sidebarState,\n workspaceStore,\n} = defineProps<\n Omit<ModalProps, 'options'> & { options: ApiClientOptionsRef }\n>()\n\nconst activeWorkspace: ScalarListboxOption = {\n label: 'default',\n id: 'default',\n}\n\n/** Controls the visibility of the sidebar. */\nconst isSidebarOpen = ref(false)\n\n/** Initialize modal events */\ninitializeModalEvents({\n eventBus,\n isSidebarOpen,\n requestBodyCompositionSelection,\n sidebarState,\n modalState,\n store: workspaceStore,\n})\n\n/** Register global hotkeys for the app, passing the workspace event bus and layout state */\nuseGlobalHotKeys(eventBus, 'modal', () => !modalState.open)\n\n/** Clean up on close */\nconst cleanUp = () => {\n eventBus.emit('operation:cancel:request')\n}\n\nconst isLocked = useScrollLock(() => {\n if (typeof window !== 'undefined') {\n return window.document.body\n }\n return null\n})\n\nwatch(\n () => modalState.open,\n (open) => {\n // Make sure scrolling is locked or unlocked when the modal is opened or closed\n isLocked.value = open\n\n if (!open) {\n cleanUp()\n }\n },\n)\n\n// Ensure we add our scalar wrapper class to the headless ui root\nonBeforeUnmount(() => cleanUp())\n\n/** Default sidebar width in pixels. */\nconst DEFAULT_SIDEBAR_WIDTH = 288\n\n/** Width of the sidebar, with fallback to default. */\nconst sidebarWidth = computed(\n () =>\n workspaceStore?.workspace?.['x-scalar-sidebar-width'] ??\n DEFAULT_SIDEBAR_WIDTH,\n)\n\n/** Handler for sidebar width changes. */\nconst handleSidebarWidthUpdate = (width: number) =>\n workspaceStore?.update('x-scalar-sidebar-width', width)\n\n/**\n * Merged environment variables from workspace and document levels.\n * Variables from both sources are combined, with document variables\n * taking precedence in case of naming conflicts.\n */\nconst environment = computed(\n () => getActiveEnvironment(workspaceStore, document.value).environment,\n)\n\ndefineExpose({\n sidebarWidth,\n environment,\n})\n</script>\n\n<template>\n <ModalClientContainer :modalState>\n <!-- Toasts -->\n <ScalarToasts />\n\n <!-- If we have a document, path and method, render the operation -->\n <main\n v-if=\"document.value && path?.value && method?.value\"\n class=\"relative flex h-full min-h-0 w-full flex-1\">\n <SidebarToggle\n v-model=\"isSidebarOpen\"\n class=\"absolute top-2 left-3 z-2\" />\n <Sidebar\n v-show=\"isSidebarOpen\"\n v-model:sidebarWidth=\"sidebarWidth\"\n :activeWorkspace=\"activeWorkspace\"\n class=\"h-full max-md:absolute! max-md:w-full!\"\n :documents=\"[document.value]\"\n :eventBus\n :isDroppable=\"() => false\"\n layout=\"modal\"\n :sidebarState=\"sidebarState.state\"\n :workspaces=\"[]\"\n @selectItem=\"sidebarState.handleSelectItem\"\n @update:sidebarWidth=\"handleSidebarWidthUpdate\" />\n <Operation\n :activeWorkspace=\"activeWorkspace\"\n class=\"flex-1\"\n :document=\"document.value\"\n :documentSlug=\"document.value['x-scalar-navigation']?.id ?? ''\"\n :environment\n :eventBus\n :exampleName=\"exampleName?.value\"\n layout=\"modal\"\n :method=\"method?.value\"\n :options\n :path=\"path?.value\"\n :plugins\n :requestBodyCompositionSelection=\"requestBodyCompositionSelection.value\"\n :workspaceStore />\n </main>\n <!-- Empty state -->\n <div\n v-else\n class=\"flex h-full w-full items-center justify-center\">\n <span class=\"text-c-3\">No document selected</span>\n </div>\n </ModalClientContainer>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8EA,MAAM,kBAAuC;GAC3C,OAAO;GACP,IAAI;GACN;;EAGA,MAAM,gBAAgB,IAAI,MAAK;;AAG/B,wBAAsB;GACpB,UAAO,QAAA;GACP;GACA,iCAA8B,QAAA;GAC9B,cAAW,QAAA;GACX,YAAS,QAAA;GACT,OAAO,QAAA;GACR,CAAA;;AAGD,mBAAiB,QAAA,UAAU,eAAe,CAAC,QAAA,WAAW,KAAI;;EAG1D,MAAM,gBAAgB;AACpB,WAAA,SAAS,KAAK,2BAA0B;;EAG1C,MAAM,WAAW,oBAAoB;AACnC,OAAI,OAAO,WAAW,YACpB,QAAO,OAAO,SAAS;AAEzB,UAAO;IACR;AAED,cACQ,QAAA,WAAW,OAChB,SAAS;AAER,YAAS,QAAQ;AAEjB,OAAI,CAAC,KACH,UAAQ;IAGd;AAGA,wBAAsB,SAAS,CAAA;;EAG/B,MAAM,wBAAwB;;EAG9B,MAAM,eAAe,eAEjB,QAAA,gBAAgB,YAAY,6BAC5B,sBACJ;;EAGA,MAAM,4BAA4B,UAChC,QAAA,gBAAgB,OAAO,0BAA0B,MAAK;;;;;;EAOxD,MAAM,cAAc,eACZ,qBAAqB,QAAA,gBAAgB,QAAA,SAAS,MAAM,CAAC,YAC7D;AAEA,WAAa;GACX;GACA;GACD,CAAA;;uBAIC,YA8CuB,8BAAA,EA9CA,YAAA,QAAA,YAAU,EAAA;2BAEf,CAAhB,YAAgB,MAAA,aAAA,CAAA,EAIR,QAAA,SAAS,SAAS,QAAA,MAAM,SAAS,QAAA,QAAQ,SAAA,WAAA,EADjD,mBAkCO,QAlCP,YAkCO;KA/BL,YAEsC,MAAA,sBAAA,EAAA;kBAD3B,cAAA;iFAAa,QAAA;MACtB,OAAM;;oBACR,YAYoD,MAAA,gBAAA,EAAA;MAV1C,cAAc,aAAA;mFAAY,QAAA,SAUZ,yBAAA;MATJ;MAClB,OAAM;MACL,WAAS,CAAG,QAAA,SAAS,MAAK;MAC1B,UAAA,QAAA;MACA,mBAAa;MACd,QAAO;MACN,cAAc,QAAA,aAAa;MAC3B,YAAY,EAAE;MACd,cAAY,QAAA,aAAa;;;;;;;kBAVlB,cAAA,MAAa,CAAA,CAAA;KAYvB,YAcoB,mBAAA;MAbA;MAClB,OAAM;MACL,UAAU,QAAA,SAAS;MACnB,cAAc,QAAA,SAAS,MAAK,wBAAyB,MAAE;MACvD,aAAA,YAAA;MACA,UAAA,QAAA;MACA,aAAa,QAAA,aAAa;MAC3B,QAAO;MACN,QAAQ,QAAA,QAAQ;MAChB,SAAA,QAAA;MACA,MAAM,QAAA,MAAM;MACZ,SAAA,QAAA;MACA,iCAAiC,QAAA,gCAAgC;MACjE,gBAAA,QAAA;;;;;;;;;;;;;;wBAGL,mBAIM,OAJN,YAIM,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CADJ,mBAAkD,QAAA,EAA5C,OAAM,YAAU,EAAC,wBAAoB,GAAA,CAAA,EAAA,CAAA,EAAA,CAAA"}
import type { RouteProps } from '../../../v2/features/app/helpers/routes.js';
import type { ApiClientModalOptionsRef } from '../../../v2/features/modal/helpers/types';
/**

@@ -14,9 +13,5 @@ * Operation example page

declare const __VLS_export: import("vue").DefineComponent<RouteProps & {
/** Subset of config options for the modal */
options?: ApiClientModalOptionsRef;
/** Selected anyOf/oneOf request-body variants keyed by schema path */
requestBodyCompositionSelection?: Record<string, number>;
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<RouteProps & {
/** Subset of config options for the modal */
options?: ApiClientModalOptionsRef;
/** Selected anyOf/oneOf request-body variants keyed by schema path */

@@ -23,0 +18,0 @@ requestBodyCompositionSelection?: Record<string, number>;

@@ -1,1 +0,1 @@

{"version":3,"file":"Operation.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/features/operation/Operation.vue"],"names":[],"mappings":"AAoMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAA;AAElE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAA;AAGjF;;;;;;;GAOG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;IAEd,6CAA6C;cACnC,wBAAwB;IAClC,sEAAsE;sCACpC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;;IAHxD,6CAA6C;cACnC,wBAAwB;IAClC,sEAAsE;sCACpC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;iGAyPxD,CAAC"}
{"version":3,"file":"Operation.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/features/operation/Operation.vue"],"names":[],"mappings":"AAiMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAA;AAIlE;;;;;;;GAOG;wBACkB,OAAO,YAAY;AAAxC,wBAAyC;AAGzC,QAAA,MAAM,YAAY;IAEd,sEAAsE;sCACpC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;;IADxD,sEAAsE;sCACpC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;iGAyPxD,CAAC"}

@@ -1,1 +0,1 @@

{"version":3,"file":"Operation.vue.js","names":[],"sources":["../../../../src/v2/features/operation/Operation.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Operation example page\n *\n * Displays an operation with a specific example selected\n * - View example request data\n * - Modify example request data\n * - Send example request\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { isElectron } from '@scalar/helpers/general/is-electron'\nimport {\n getActiveProxyUrl,\n getRequestExampleContext,\n} from '@scalar/workspace-store/request-example'\nimport { computed, toValue } from 'vue'\n\nimport { OperationBlock } from '@/v2/blocks/operation-block'\nimport { APP_VERSION } from '@/v2/constants'\nimport type { RouteProps } from '@/v2/features/app/helpers/routes'\nimport { mapHiddenClientsConfig } from '@/v2/features/modal/helpers/map-hidden-clients-config'\nimport type { ApiClientModalOptionsRef } from '@/v2/features/modal/helpers/types'\n\nconst {\n document,\n layout,\n eventBus,\n path,\n method,\n environment,\n exampleName,\n options,\n workspaceStore,\n plugins,\n documentSlug,\n} = defineProps<\n RouteProps & {\n /** Subset of config options for the modal */\n options?: ApiClientModalOptionsRef\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection?: Record<string, number>\n }\n>()\n\n/**\n * Shared request-example context (operation, servers, auth scope, cookies). Recomputed when any\n * underlying workspace or route input changes — same reactivity as the previous local computeds.\n */\nconst requestExample = computed(() => {\n if (!path || !method || !exampleName || !document) {\n return null\n }\n\n const result = getRequestExampleContext(\n workspaceStore,\n documentSlug,\n { path, method, exampleName },\n {\n baseServerUrl: toValue(options)?.baseServerURL,\n fallbackDocument: document,\n isElectron: isElectron(),\n layout: layout === 'web' ? 'web' : 'other',\n servers: toValue(options)?.servers,\n appVersion: APP_VERSION,\n authentication: toValue(options)?.authentication,\n },\n )\n\n return result.ok ? result.data : null\n})\n\nconst operation = computed(() => requestExample.value?.operation ?? null)\nconst workspaceCookies = computed(\n () => requestExample.value?.cookies.workspace ?? [],\n)\nconst documentCookies = computed(\n () => requestExample.value?.cookies.document ?? [],\n)\nconst servers = computed(() => requestExample.value?.servers.list ?? [])\nconst selectedServer = computed(\n () => requestExample.value?.servers.selected ?? null,\n)\nconst serverMeta = computed(\n () => requestExample.value?.servers.meta ?? { type: 'document' as const },\n)\n\nconst securitySchemes = computed(\n () => requestExample.value?.security.schemes ?? {},\n)\n\nconst selectedSecurity = computed(\n () =>\n requestExample.value?.security.selected ?? {\n selectedIndex: -1,\n selectedSchemes: [],\n },\n)\nconst selectedSecuritySchemes = computed(\n () => requestExample.value?.security.selectedSchemes ?? [],\n)\nconst securityRequirements = computed(\n () => requestExample.value?.security.requirements ?? [],\n)\nconst authMeta = computed(\n () => requestExample.value?.security.meta ?? { type: 'document' as const },\n)\n\nconst defaultHeaders = computed(\n () => requestExample.value?.headers.default ?? {},\n)\n\n/** Combine environments from document and workspace into a unique array of environment names */\nconst environments = computed(() => {\n return Array.from(\n new Set(\n Object.keys({\n ...document?.['x-scalar-environments'],\n ...workspaceStore.workspace['x-scalar-environments'],\n }),\n ),\n )\n})\n\n/** Temporarily use the old config.hiddenClients until we migrate to the new httpClients config */\nconst httpClients = computed(() =>\n mapHiddenClientsConfig(toValue(options)?.hiddenClients),\n)\n</script>\n\n<template>\n <!-- Operation exists -->\n <template v-if=\"path && method && exampleName && operation && document\">\n <OperationBlock\n :activeEnvironment=\"\n workspaceStore.workspace['x-scalar-active-environment']\n \"\n :appVersion=\"APP_VERSION\"\n :authMeta\n :defaultHeaders\n :document\n :documentCookies\n :documentSecurity=\"document?.security ?? []\"\n :documentUrl=\"document?.['x-scalar-original-source-url']\"\n :environment\n :environments\n :eventBus\n :exampleKey=\"exampleName\"\n :hideClientButton=\"toValue(options)?.hideClientButton ?? false\"\n :history=\"workspaceStore.history.getHistory(documentSlug, path, method)\"\n :httpClients\n :layout\n :method\n :operation\n :options\n :path\n :plugins=\"plugins\"\n :proxyUrl=\"\n getActiveProxyUrl(\n workspaceStore.workspace['x-scalar-active-proxy'],\n layout === 'web' ? 'web' : 'other',\n ) ?? ''\n \"\n :requestBodyCompositionSelection\n :securityRequirements=\"securityRequirements\"\n :securitySchemes\n :selectedClient=\"workspaceStore.workspace['x-scalar-default-client']\"\n :selectedSecurity=\"selectedSecurity\"\n :selectedSecuritySchemes=\"selectedSecuritySchemes\"\n :server=\"selectedServer\"\n :serverMeta\n :servers\n :workspaceCookies />\n </template>\n\n <!-- Empty state -->\n <div\n v-else\n class=\"flex h-full w-full items-center justify-center\">\n <span class=\"text-c-3\">Select an operation to view details</span>\n </div>\n</template>\n"],"mappings":""}
{"version":3,"file":"Operation.vue.js","names":[],"sources":["../../../../src/v2/features/operation/Operation.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Operation example page\n *\n * Displays an operation with a specific example selected\n * - View example request data\n * - Modify example request data\n * - Send example request\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { isElectron } from '@scalar/helpers/general/is-electron'\nimport {\n getActiveProxyUrl,\n getRequestExampleContext,\n} from '@scalar/workspace-store/request-example'\nimport { computed, toValue } from 'vue'\n\nimport { OperationBlock } from '@/v2/blocks/operation-block'\nimport { APP_VERSION } from '@/v2/constants'\nimport type { RouteProps } from '@/v2/features/app/helpers/routes'\nimport { mapHiddenClientsConfig } from '@/v2/features/modal/helpers/map-hidden-clients-config'\n\nconst {\n document,\n layout,\n eventBus,\n path,\n method,\n environment,\n exampleName,\n options,\n workspaceStore,\n plugins,\n documentSlug,\n} = defineProps<\n RouteProps & {\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection?: Record<string, number>\n }\n>()\n\n/**\n * Shared request-example context (operation, servers, auth scope, cookies). Recomputed when any\n * underlying workspace or route input changes — same reactivity as the previous local computeds.\n */\nconst requestExample = computed(() => {\n if (!path || !method || !exampleName || !document) {\n return null\n }\n\n const result = getRequestExampleContext(\n workspaceStore,\n documentSlug,\n { path, method, exampleName },\n {\n baseServerUrl: toValue(options)?.baseServerURL,\n fallbackDocument: document,\n isElectron: isElectron(),\n layout: layout === 'web' ? 'web' : 'other',\n servers: toValue(options)?.servers,\n appVersion: APP_VERSION,\n authentication: toValue(options)?.authentication,\n },\n )\n\n return result.ok ? result.data : null\n})\n\nconst operation = computed(() => requestExample.value?.operation ?? null)\nconst workspaceCookies = computed(\n () => requestExample.value?.cookies.workspace ?? [],\n)\nconst documentCookies = computed(\n () => requestExample.value?.cookies.document ?? [],\n)\nconst servers = computed(() => requestExample.value?.servers.list ?? [])\nconst selectedServer = computed(\n () => requestExample.value?.servers.selected ?? null,\n)\nconst serverMeta = computed(\n () => requestExample.value?.servers.meta ?? { type: 'document' as const },\n)\n\nconst securitySchemes = computed(\n () => requestExample.value?.security.schemes ?? {},\n)\n\nconst selectedSecurity = computed(\n () =>\n requestExample.value?.security.selected ?? {\n selectedIndex: -1,\n selectedSchemes: [],\n },\n)\nconst selectedSecuritySchemes = computed(\n () => requestExample.value?.security.selectedSchemes ?? [],\n)\nconst securityRequirements = computed(\n () => requestExample.value?.security.requirements ?? [],\n)\nconst authMeta = computed(\n () => requestExample.value?.security.meta ?? { type: 'document' as const },\n)\n\nconst defaultHeaders = computed(\n () => requestExample.value?.headers.default ?? {},\n)\n\n/** Combine environments from document and workspace into a unique array of environment names */\nconst environments = computed(() => {\n return Array.from(\n new Set(\n Object.keys({\n ...document?.['x-scalar-environments'],\n ...workspaceStore.workspace['x-scalar-environments'],\n }),\n ),\n )\n})\n\n/** Temporarily use the old config.hiddenClients until we migrate to the new httpClients config */\nconst httpClients = computed(() =>\n mapHiddenClientsConfig(toValue(options)?.hiddenClients),\n)\n</script>\n\n<template>\n <!-- Operation exists -->\n <template v-if=\"path && method && exampleName && operation && document\">\n <OperationBlock\n :activeEnvironment=\"\n workspaceStore.workspace['x-scalar-active-environment']\n \"\n :appVersion=\"APP_VERSION\"\n :authMeta\n :defaultHeaders\n :document\n :documentCookies\n :documentSecurity=\"document?.security ?? []\"\n :documentUrl=\"document?.['x-scalar-original-source-url']\"\n :environment\n :environments\n :eventBus\n :exampleKey=\"exampleName\"\n :hideClientButton=\"toValue(options)?.hideClientButton ?? false\"\n :history=\"workspaceStore.history.getHistory(documentSlug, path, method)\"\n :httpClients\n :layout\n :method\n :operation\n :options\n :path\n :plugins=\"plugins\"\n :proxyUrl=\"\n getActiveProxyUrl(\n workspaceStore.workspace['x-scalar-active-proxy'],\n layout === 'web' ? 'web' : 'other',\n ) ?? ''\n \"\n :requestBodyCompositionSelection\n :securityRequirements=\"securityRequirements\"\n :securitySchemes\n :selectedClient=\"workspaceStore.workspace['x-scalar-default-client']\"\n :selectedSecurity=\"selectedSecurity\"\n :selectedSecuritySchemes=\"selectedSecuritySchemes\"\n :server=\"selectedServer\"\n :serverMeta\n :servers\n :workspaceCookies />\n </template>\n\n <!-- Empty state -->\n <div\n v-else\n class=\"flex h-full w-full items-center justify-center\">\n <span class=\"text-c-3\">Select an operation to view details</span>\n </div>\n</template>\n"],"mappings":""}

@@ -1,1 +0,1 @@

{"version":3,"file":"Operation.vue.script.js","names":[],"sources":["../../../../src/v2/features/operation/Operation.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Operation example page\n *\n * Displays an operation with a specific example selected\n * - View example request data\n * - Modify example request data\n * - Send example request\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { isElectron } from '@scalar/helpers/general/is-electron'\nimport {\n getActiveProxyUrl,\n getRequestExampleContext,\n} from '@scalar/workspace-store/request-example'\nimport { computed, toValue } from 'vue'\n\nimport { OperationBlock } from '@/v2/blocks/operation-block'\nimport { APP_VERSION } from '@/v2/constants'\nimport type { RouteProps } from '@/v2/features/app/helpers/routes'\nimport { mapHiddenClientsConfig } from '@/v2/features/modal/helpers/map-hidden-clients-config'\nimport type { ApiClientModalOptionsRef } from '@/v2/features/modal/helpers/types'\n\nconst {\n document,\n layout,\n eventBus,\n path,\n method,\n environment,\n exampleName,\n options,\n workspaceStore,\n plugins,\n documentSlug,\n} = defineProps<\n RouteProps & {\n /** Subset of config options for the modal */\n options?: ApiClientModalOptionsRef\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection?: Record<string, number>\n }\n>()\n\n/**\n * Shared request-example context (operation, servers, auth scope, cookies). Recomputed when any\n * underlying workspace or route input changes — same reactivity as the previous local computeds.\n */\nconst requestExample = computed(() => {\n if (!path || !method || !exampleName || !document) {\n return null\n }\n\n const result = getRequestExampleContext(\n workspaceStore,\n documentSlug,\n { path, method, exampleName },\n {\n baseServerUrl: toValue(options)?.baseServerURL,\n fallbackDocument: document,\n isElectron: isElectron(),\n layout: layout === 'web' ? 'web' : 'other',\n servers: toValue(options)?.servers,\n appVersion: APP_VERSION,\n authentication: toValue(options)?.authentication,\n },\n )\n\n return result.ok ? result.data : null\n})\n\nconst operation = computed(() => requestExample.value?.operation ?? null)\nconst workspaceCookies = computed(\n () => requestExample.value?.cookies.workspace ?? [],\n)\nconst documentCookies = computed(\n () => requestExample.value?.cookies.document ?? [],\n)\nconst servers = computed(() => requestExample.value?.servers.list ?? [])\nconst selectedServer = computed(\n () => requestExample.value?.servers.selected ?? null,\n)\nconst serverMeta = computed(\n () => requestExample.value?.servers.meta ?? { type: 'document' as const },\n)\n\nconst securitySchemes = computed(\n () => requestExample.value?.security.schemes ?? {},\n)\n\nconst selectedSecurity = computed(\n () =>\n requestExample.value?.security.selected ?? {\n selectedIndex: -1,\n selectedSchemes: [],\n },\n)\nconst selectedSecuritySchemes = computed(\n () => requestExample.value?.security.selectedSchemes ?? [],\n)\nconst securityRequirements = computed(\n () => requestExample.value?.security.requirements ?? [],\n)\nconst authMeta = computed(\n () => requestExample.value?.security.meta ?? { type: 'document' as const },\n)\n\nconst defaultHeaders = computed(\n () => requestExample.value?.headers.default ?? {},\n)\n\n/** Combine environments from document and workspace into a unique array of environment names */\nconst environments = computed(() => {\n return Array.from(\n new Set(\n Object.keys({\n ...document?.['x-scalar-environments'],\n ...workspaceStore.workspace['x-scalar-environments'],\n }),\n ),\n )\n})\n\n/** Temporarily use the old config.hiddenClients until we migrate to the new httpClients config */\nconst httpClients = computed(() =>\n mapHiddenClientsConfig(toValue(options)?.hiddenClients),\n)\n</script>\n\n<template>\n <!-- Operation exists -->\n <template v-if=\"path && method && exampleName && operation && document\">\n <OperationBlock\n :activeEnvironment=\"\n workspaceStore.workspace['x-scalar-active-environment']\n \"\n :appVersion=\"APP_VERSION\"\n :authMeta\n :defaultHeaders\n :document\n :documentCookies\n :documentSecurity=\"document?.security ?? []\"\n :documentUrl=\"document?.['x-scalar-original-source-url']\"\n :environment\n :environments\n :eventBus\n :exampleKey=\"exampleName\"\n :hideClientButton=\"toValue(options)?.hideClientButton ?? false\"\n :history=\"workspaceStore.history.getHistory(documentSlug, path, method)\"\n :httpClients\n :layout\n :method\n :operation\n :options\n :path\n :plugins=\"plugins\"\n :proxyUrl=\"\n getActiveProxyUrl(\n workspaceStore.workspace['x-scalar-active-proxy'],\n layout === 'web' ? 'web' : 'other',\n ) ?? ''\n \"\n :requestBodyCompositionSelection\n :securityRequirements=\"securityRequirements\"\n :securitySchemes\n :selectedClient=\"workspaceStore.workspace['x-scalar-default-client']\"\n :selectedSecurity=\"selectedSecurity\"\n :selectedSecuritySchemes=\"selectedSecuritySchemes\"\n :server=\"selectedServer\"\n :serverMeta\n :servers\n :workspaceCookies />\n </template>\n\n <!-- Empty state -->\n <div\n v-else\n class=\"flex h-full w-full items-center justify-center\">\n <span class=\"text-c-3\">Select an operation to view details</span>\n </div>\n</template>\n"],"mappings":"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"}
{"version":3,"file":"Operation.vue.script.js","names":[],"sources":["../../../../src/v2/features/operation/Operation.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Operation example page\n *\n * Displays an operation with a specific example selected\n * - View example request data\n * - Modify example request data\n * - Send example request\n */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { isElectron } from '@scalar/helpers/general/is-electron'\nimport {\n getActiveProxyUrl,\n getRequestExampleContext,\n} from '@scalar/workspace-store/request-example'\nimport { computed, toValue } from 'vue'\n\nimport { OperationBlock } from '@/v2/blocks/operation-block'\nimport { APP_VERSION } from '@/v2/constants'\nimport type { RouteProps } from '@/v2/features/app/helpers/routes'\nimport { mapHiddenClientsConfig } from '@/v2/features/modal/helpers/map-hidden-clients-config'\n\nconst {\n document,\n layout,\n eventBus,\n path,\n method,\n environment,\n exampleName,\n options,\n workspaceStore,\n plugins,\n documentSlug,\n} = defineProps<\n RouteProps & {\n /** Selected anyOf/oneOf request-body variants keyed by schema path */\n requestBodyCompositionSelection?: Record<string, number>\n }\n>()\n\n/**\n * Shared request-example context (operation, servers, auth scope, cookies). Recomputed when any\n * underlying workspace or route input changes — same reactivity as the previous local computeds.\n */\nconst requestExample = computed(() => {\n if (!path || !method || !exampleName || !document) {\n return null\n }\n\n const result = getRequestExampleContext(\n workspaceStore,\n documentSlug,\n { path, method, exampleName },\n {\n baseServerUrl: toValue(options)?.baseServerURL,\n fallbackDocument: document,\n isElectron: isElectron(),\n layout: layout === 'web' ? 'web' : 'other',\n servers: toValue(options)?.servers,\n appVersion: APP_VERSION,\n authentication: toValue(options)?.authentication,\n },\n )\n\n return result.ok ? result.data : null\n})\n\nconst operation = computed(() => requestExample.value?.operation ?? null)\nconst workspaceCookies = computed(\n () => requestExample.value?.cookies.workspace ?? [],\n)\nconst documentCookies = computed(\n () => requestExample.value?.cookies.document ?? [],\n)\nconst servers = computed(() => requestExample.value?.servers.list ?? [])\nconst selectedServer = computed(\n () => requestExample.value?.servers.selected ?? null,\n)\nconst serverMeta = computed(\n () => requestExample.value?.servers.meta ?? { type: 'document' as const },\n)\n\nconst securitySchemes = computed(\n () => requestExample.value?.security.schemes ?? {},\n)\n\nconst selectedSecurity = computed(\n () =>\n requestExample.value?.security.selected ?? {\n selectedIndex: -1,\n selectedSchemes: [],\n },\n)\nconst selectedSecuritySchemes = computed(\n () => requestExample.value?.security.selectedSchemes ?? [],\n)\nconst securityRequirements = computed(\n () => requestExample.value?.security.requirements ?? [],\n)\nconst authMeta = computed(\n () => requestExample.value?.security.meta ?? { type: 'document' as const },\n)\n\nconst defaultHeaders = computed(\n () => requestExample.value?.headers.default ?? {},\n)\n\n/** Combine environments from document and workspace into a unique array of environment names */\nconst environments = computed(() => {\n return Array.from(\n new Set(\n Object.keys({\n ...document?.['x-scalar-environments'],\n ...workspaceStore.workspace['x-scalar-environments'],\n }),\n ),\n )\n})\n\n/** Temporarily use the old config.hiddenClients until we migrate to the new httpClients config */\nconst httpClients = computed(() =>\n mapHiddenClientsConfig(toValue(options)?.hiddenClients),\n)\n</script>\n\n<template>\n <!-- Operation exists -->\n <template v-if=\"path && method && exampleName && operation && document\">\n <OperationBlock\n :activeEnvironment=\"\n workspaceStore.workspace['x-scalar-active-environment']\n \"\n :appVersion=\"APP_VERSION\"\n :authMeta\n :defaultHeaders\n :document\n :documentCookies\n :documentSecurity=\"document?.security ?? []\"\n :documentUrl=\"document?.['x-scalar-original-source-url']\"\n :environment\n :environments\n :eventBus\n :exampleKey=\"exampleName\"\n :hideClientButton=\"toValue(options)?.hideClientButton ?? false\"\n :history=\"workspaceStore.history.getHistory(documentSlug, path, method)\"\n :httpClients\n :layout\n :method\n :operation\n :options\n :path\n :plugins=\"plugins\"\n :proxyUrl=\"\n getActiveProxyUrl(\n workspaceStore.workspace['x-scalar-active-proxy'],\n layout === 'web' ? 'web' : 'other',\n ) ?? ''\n \"\n :requestBodyCompositionSelection\n :securityRequirements=\"securityRequirements\"\n :securitySchemes\n :selectedClient=\"workspaceStore.workspace['x-scalar-default-client']\"\n :selectedSecurity=\"selectedSecurity\"\n :selectedSecuritySchemes=\"selectedSecuritySchemes\"\n :server=\"selectedServer\"\n :serverMeta\n :servers\n :workspaceCookies />\n </template>\n\n <!-- Empty state -->\n <div\n v-else\n class=\"flex h-full w-full items-center justify-center\">\n <span class=\"text-c-3\">Select an operation to view details</span>\n </div>\n</template>\n"],"mappings":"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"}

@@ -21,3 +21,3 @@ {

],
"version": "3.1.0",
"version": "3.2.0",
"engines": {

@@ -336,17 +336,17 @@ "node": ">=22"

"zod": "^4.3.5",
"@scalar/components": "0.22.1",
"@scalar/helpers": "0.5.1",
"@scalar/icons": "0.7.2",
"@scalar/oas-utils": "0.13.1",
"@scalar/components": "0.22.2",
"@scalar/openapi-types": "0.8.0",
"@scalar/json-magic": "0.12.7",
"@scalar/oas-utils": "0.13.0",
"@scalar/icons": "0.7.2",
"@scalar/openapi-types": "0.7.0",
"@scalar/postman-to-openapi": "0.6.3",
"@scalar/sidebar": "0.9.2",
"@scalar/postman-to-openapi": "0.7.0",
"@scalar/sidebar": "0.9.3",
"@scalar/snippetz": "0.9.1",
"@scalar/themes": "0.15.3",
"@scalar/types": "0.9.1",
"@scalar/use-hooks": "0.4.3",
"@scalar/use-codemirror": "0.14.11",
"@scalar/use-hooks": "0.4.2",
"@scalar/use-toasts": "0.10.1",
"@scalar/workspace-store": "0.46.1",
"@scalar/helpers": "0.5.1"
"@scalar/use-toasts": "0.10.2",
"@scalar/workspace-store": "0.46.2"
},

@@ -366,3 +366,3 @@ "devDependencies": {

"vitest": "4.1.0",
"@scalar/pre-post-request-scripts": "0.4.3"
"@scalar/pre-post-request-scripts": "0.4.4"
},

@@ -369,0 +369,0 @@ "scripts": {

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display