mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-17 08:05:19 +00:00
4f039ecb2b
* wip * feat: add scalar api client * fix: pr feedback * feat: add scalar react client package, remove vueary * feat: add scalar proxy * Move dependencies to package * Format once * Rename prop * Use react context and simplify lazy loading * Add loading state * Format * Move styles * bun install * bun * fix: remove extraneous api-reference package * feat: make operation functional with spec in client * fix: column bug and http request type wrapping * fix: add scalar api reference package * Format * bun install * fix: scrolling in scalar modal * Lazy load operations data in component * fix: change dependency from api-reference to oas-utils to reduce size * bun install * Log error in the worker proxy * Cleanup * Comment "mode" * Without credentials and referrerPolicy --------- Co-authored-by: Samy Pessé <samypesse@gmail.com> Co-authored-by: Amrit <amrit@hockey-community.com>
130 lines
4.3 KiB
TypeScript
130 lines
4.3 KiB
TypeScript
'use client';
|
|
|
|
import classNames from 'classnames';
|
|
import React from 'react';
|
|
|
|
/**
|
|
* To optimize rendering, most of the components are server-components,
|
|
* and the interactiveness is mainly handled by a few key components like this one.
|
|
*/
|
|
export function InteractiveSection(props: {
|
|
id?: string;
|
|
/** Class name to be set on the section, sub-elements will use it as prefix */
|
|
className: string;
|
|
/** If true, the content can be toggeable */
|
|
toggeable?: boolean;
|
|
/** Default state of the toggle */
|
|
defaultOpened?: boolean;
|
|
/** Icons to display for the toggle */
|
|
toggleOpenIcon?: React.ReactNode;
|
|
toggleCloseIcon?: React.ReactNode;
|
|
/** Tabs of content to display */
|
|
tabs?: Array<{
|
|
key: string;
|
|
label: string;
|
|
body: React.ReactNode;
|
|
}>;
|
|
/** Default tab to have opened */
|
|
defaultTab?: string;
|
|
/** Content of the header */
|
|
header: React.ReactNode;
|
|
/** Body of the section */
|
|
children?: React.ReactNode;
|
|
/** Children to display within the container */
|
|
overlay?: React.ReactNode;
|
|
}) {
|
|
const {
|
|
id,
|
|
className,
|
|
toggeable = false,
|
|
defaultOpened = true,
|
|
tabs = [],
|
|
defaultTab = tabs[0]?.key,
|
|
header,
|
|
children,
|
|
overlay,
|
|
toggleOpenIcon = '▶',
|
|
toggleCloseIcon = '▼',
|
|
} = props;
|
|
|
|
const [opened, setOpened] = React.useState(defaultOpened);
|
|
const [selectedTab, setSelectedTab] = React.useState(defaultTab);
|
|
|
|
const tabBody = tabs.find((tab) => tab.key === selectedTab)?.body;
|
|
|
|
return (
|
|
<div
|
|
id={id}
|
|
className={classNames(
|
|
'openapi-section',
|
|
toggeable ? 'openapi-section-toggeable' : null,
|
|
className,
|
|
toggeable ? `${className}-${opened ? 'opened' : 'closed'}` : null,
|
|
)}
|
|
>
|
|
<div
|
|
onClick={() => {
|
|
if (toggeable) {
|
|
setOpened(!opened);
|
|
}
|
|
}}
|
|
className={classNames('openapi-section-header', `${className}-header`)}
|
|
>
|
|
<div
|
|
className={classNames(
|
|
'openapi-section-header-content',
|
|
`${className}-header-content`,
|
|
)}
|
|
>
|
|
{header}
|
|
</div>
|
|
<div
|
|
className={classNames(
|
|
'openapi-section-header-controls',
|
|
`${className}-header-controls`,
|
|
)}
|
|
onClick={(event) => {
|
|
event.stopPropagation();
|
|
}}
|
|
>
|
|
{tabs.length ? (
|
|
<select
|
|
className={classNames(
|
|
'openapi-section-select',
|
|
'openapi-select',
|
|
`${className}-tabs-select`,
|
|
)}
|
|
value={selectedTab}
|
|
onChange={(event) => {
|
|
setSelectedTab(event.target.value);
|
|
setOpened(true);
|
|
}}
|
|
>
|
|
{tabs.map((tab) => (
|
|
<option key={tab.key} value={tab.key}>
|
|
{tab.label}
|
|
</option>
|
|
))}
|
|
</select>
|
|
) : null}
|
|
{(children || tabBody) && toggeable ? (
|
|
<button
|
|
className={classNames('openapi-section-toggle', `${className}-toggle`)}
|
|
onClick={() => setOpened(!opened)}
|
|
>
|
|
{opened ? toggleCloseIcon : toggleOpenIcon}
|
|
</button>
|
|
) : null}
|
|
</div>
|
|
</div>
|
|
{(!toggeable || opened) && (children || tabBody) ? (
|
|
<div className={classNames('openapi-section-body', `${className}-body`)}>
|
|
{children}
|
|
{tabBody}
|
|
</div>
|
|
) : null}
|
|
{overlay}
|
|
</div>
|
|
);
|
|
}
|