diff --git a/.changeset/hip-moons-collect.md b/.changeset/hip-moons-collect.md new file mode 100644 index 000000000..954a60954 --- /dev/null +++ b/.changeset/hip-moons-collect.md @@ -0,0 +1,5 @@ +--- +'@gitbook/react-openapi': minor +--- + +Update Scalar to the latest version, with faster performances and an improved experience diff --git a/bun.lockb b/bun.lockb index d7620a634..de48a1be6 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPI.tsx b/packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPI.tsx index e5dcbe35c..f3eda24fb 100644 --- a/packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPI.tsx +++ b/packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPI.tsx @@ -34,7 +34,7 @@ export async function OpenAPI(props: BlockProps) { async function OpenAPIBody(props: BlockProps) { const { block, context } = props; - const { data, error } = await fetchOpenAPIBlock(block, context.resolveContentRef); + const { data, specUrl, error } = await fetchOpenAPIBlock(block, context.resolveContentRef); if (error) { return ( @@ -46,7 +46,7 @@ async function OpenAPIBody(props: BlockProps) { ); } - if (!data) { + if (!data || !specUrl) { return null; } @@ -60,6 +60,7 @@ async function OpenAPIBody(props: BlockProps) { }, CodeBlock: PlainCodeBlock, defaultInteractiveOpened: context.mode === 'print', + specUrl, }} className="openapi-block" /> diff --git a/packages/gitbook/src/components/DocumentView/OpenAPI/scalar.css b/packages/gitbook/src/components/DocumentView/OpenAPI/scalar.css index e23957d82..f75a53ecc 100644 --- a/packages/gitbook/src/components/DocumentView/OpenAPI/scalar.css +++ b/packages/gitbook/src/components/DocumentView/OpenAPI/scalar.css @@ -1,4 +1,7 @@ +@import '@scalar/api-client-react/style.css'; + .light .scalar-modal-layout, +.light .scalar-app, .light .scalar { --scalar-color-1: color-mix( in srgb, @@ -50,8 +53,13 @@ --scalar-button-1: rgb(49 53 56); --scalar-button-1-color: #fff; --scalar-button-1-hover: rgb(28 31 33); + + --scalar-shadow-1: 0 1px 3px 0 rgba(0, 0, 0, 0.11); + --scalar-shadow-2: rgba(0, 0, 0, 0.08) 0px 13px 20px 0px, rgba(0, 0, 0, 0.08) 0px 3px 8px 0px, + #eeeeed 0px 0 0 1px; } .dark .scalar-modal-layout, +.dark .scalar-app, .dark .scalar { --scalar-color-1: color-mix( in srgb, @@ -102,8 +110,13 @@ --scalar-button-1: #f6f6f6; --scalar-button-1-color: #000; --scalar-button-1-hover: #e7e7e7; + + --scalar-shadow-1: 0 1px 3px 0 rgb(0, 0, 0, 0.1); + --scalar-shadow-2: rgba(15, 15, 15, 0.2) 0px 3px 6px, rgba(15, 15, 15, 0.4) 0px 9px 24px, + 0 0 0 1px rgba(255, 255, 255, 0.1); } .scalar-modal-layout, +.scalar-app, .scalar { --scalar-font: initial; --scalar-font-code: var(--font-mono); @@ -165,7 +178,7 @@ .scalar-api-client__close:hover { cursor: pointer; } -.scalar .scalar-app { +.scalar .scalar-app-layout { background: var(--scalar-background-3); height: calc(100dvh - 100px); max-width: 1280px; @@ -202,23 +215,6 @@ cursor: pointer; animation: scalardrawerexitfadein 0.35s forwards; } -.scalar .scalar-app-exit:before { - content: '\00d7'; - font-family: sans-serif; - position: absolute; - top: 0; - right: 0; - font-size: 30px; - font-weight: 100; - line-height: 50px; - right: 12px; - text-align: center; - color: white; - opacity: 0.6; -} -.scalar .scalar-app-exit:hover:before { - opacity: 1; -} @keyframes scalardrawerexitfadein { from { opacity: 0; @@ -305,11 +301,6 @@ scrollbar-width: thin; -webkit-overflow-scrolling: touch; } -@supports (-moz-appearance: none) { - .scalar .custom-scroll { - padding-right: 12px; - } -} .scalar .custom-scroll:hover { scrollbar-color: rgba(0, 0, 0, 0.24) transparent; } @@ -347,3 +338,18 @@ padding-right: 12px; } } +.dark .scalar .client-wrapper-bg-color { + background: linear-gradient( + color-mix(in srgb, var(--tw-bg-base) 6%, transparent) 1%, + color-mix(in srgb, var(--scalar-background-1) 30%, black) 9% + ); +} +.light .scalar .client-wrapper-bg-color { + background-color: var(--scalar-background-2) !important; +} +.scalar .gitbook-show { + display: block !important; +} +.scalar .gitbook-hidden { + display: none !important; +} diff --git a/packages/gitbook/src/lib/openapi.ts b/packages/gitbook/src/lib/openapi.ts index 18aff1cfc..4e9b19a4d 100644 --- a/packages/gitbook/src/lib/openapi.ts +++ b/packages/gitbook/src/lib/openapi.ts @@ -19,12 +19,12 @@ export async function fetchOpenAPIBlock( block: DocumentBlockSwagger, resolveContentRef: (ref: ContentRef) => Promise, ): Promise< - | { data: OpenAPIOperationData | null; error?: undefined } - | { error: OpenAPIFetchError; data?: undefined } + | { data: OpenAPIOperationData | null; specUrl: string | null; error?: undefined } + | { error: OpenAPIFetchError; data?: undefined; specUrl?: undefined } > { const resolved = block.data.ref ? await resolveContentRef(block.data.ref) : null; if (!resolved || !block.data.path || !block.data.method) { - return { data: null }; + return { data: null, specUrl: null }; } try { @@ -37,7 +37,7 @@ export async function fetchOpenAPIBlock( fetcher, ); - return { data }; + return { data, specUrl: resolved.href }; } catch (error) { if (error instanceof OpenAPIFetchError) { return { error }; diff --git a/packages/react-openapi/package.json b/packages/react-openapi/package.json index e66630bbd..421ec82da 100644 --- a/packages/react-openapi/package.json +++ b/packages/react-openapi/package.json @@ -9,8 +9,7 @@ }, "version": "0.5.0", "dependencies": { - "@scalar/api-client-react": "^0.3.7", - "@scalar/oas-utils": "0.1.6", + "@scalar/api-client-react": "1.0.5", "classnames": "^2.5.1", "flatted": "^3.2.9", "openapi-types": "^12.1.3", diff --git a/packages/react-openapi/src/OpenAPICodeSample.tsx b/packages/react-openapi/src/OpenAPICodeSample.tsx index 981a9ca22..0cc4db1a5 100644 --- a/packages/react-openapi/src/OpenAPICodeSample.tsx +++ b/packages/react-openapi/src/OpenAPICodeSample.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import { CodeSampleInput, codeSampleGenerators } from './code-samples'; -import { OpenAPIOperationData, toJSON } from './fetchOpenAPIOperation'; +import { OpenAPIOperationData } from './fetchOpenAPIOperation'; import { generateMediaTypeExample } from './generateSchemaExample'; import { InteractiveSection } from './InteractiveSection'; import { getServersURL } from './OpenAPIServerURL'; @@ -66,11 +66,6 @@ export function OpenAPICodeSample(props: { return null; } - async function fetchOperationData() { - 'use server'; - return toJSON(data); - } - return ( + ) } /> diff --git a/packages/react-openapi/src/OpenAPIOperation.tsx b/packages/react-openapi/src/OpenAPIOperation.tsx index 15b292142..a197fe110 100644 --- a/packages/react-openapi/src/OpenAPIOperation.tsx +++ b/packages/react-openapi/src/OpenAPIOperation.tsx @@ -7,8 +7,8 @@ import { OpenAPICodeSample } from './OpenAPICodeSample'; import { OpenAPIResponseExample } from './OpenAPIResponseExample'; import { OpenAPIServerURL } from './OpenAPIServerURL'; import { OpenAPISpec } from './OpenAPISpec'; -import { ScalarApiClient } from './ScalarApiButton'; import { OpenAPIClientContext, OpenAPIContextProps } from './types'; +import { ApiClientModalProvider } from '@scalar/api-client-react'; /** * Display an interactive OpenAPI operation. @@ -23,11 +23,15 @@ export function OpenAPIOperation(props: { const clientContext: OpenAPIClientContext = { defaultInteractiveOpened: context.defaultInteractiveOpened, + specUrl: context.specUrl, icons: context.icons, }; return ( - +

{operation.summary}

@@ -61,6 +65,6 @@ export function OpenAPIOperation(props: {
-
+ ); } diff --git a/packages/react-openapi/src/ScalarApiButton.tsx b/packages/react-openapi/src/ScalarApiButton.tsx index 0e6ceffe5..21b0b0ed1 100644 --- a/packages/react-openapi/src/ScalarApiButton.tsx +++ b/packages/react-openapi/src/ScalarApiButton.tsx @@ -1,44 +1,17 @@ 'use client'; -import { - Cookie, - getHarRequest, - getParametersFromOperation, - type TransformedOperation, - getRequestFromOperation, - Query, - Header, - RequestBody, -} from '@scalar/oas-utils'; -import React from 'react'; - -import { OpenAPIOperationData, fromJSON } from './fetchOpenAPIOperation'; -const ApiClientReact = React.lazy(async () => { - const mod = await import('@scalar/api-client-react'); - return { default: mod.ApiClientReact }; -}); - -const ScalarContext = React.createContext< - (fetchOperationData: () => Promise) => void ->(() => {}); +import { useApiClientModal } from '@scalar/api-client-react'; +import React from 'react'; /** * Button which launches the Scalar API Client */ -export function ScalarApiButton(props: { - fetchOperationData: () => Promise; -}) { - const { fetchOperationData } = props; - const open = React.useContext(ScalarContext); +export function ScalarApiButton() { + const client = useApiClientModal(); return (
-