diff --git a/cli/index.ts b/cli/index.ts index ebdb425f..3d664eda 100644 --- a/cli/index.ts +++ b/cli/index.ts @@ -340,6 +340,7 @@ async function getPageHTML( const specUrl = redocOptions.specUrl || (isURL(pathToSpec) ? pathToSpec : undefined); const store = await createStore(spec, specUrl, redocOptions); const sheet = new ServerStyleSheet(); + // @ts-ignore html = renderToString(sheet.collectStyles(React.createElement(Redoc, { store }))); css = sheet.getStyleTags(); state = await store.toJS(); diff --git a/src/common-elements/CopyButtonWrapper.tsx b/src/common-elements/CopyButtonWrapper.tsx index 3111af8d..c0546a09 100644 --- a/src/common-elements/CopyButtonWrapper.tsx +++ b/src/common-elements/CopyButtonWrapper.tsx @@ -8,36 +8,24 @@ export interface CopyButtonWrapperProps { children: (props: { renderCopyButton: () => React.ReactNode }) => React.ReactNode; } -export class CopyButtonWrapper extends React.PureComponent< - CopyButtonWrapperProps, - { tooltipShown: boolean } -> { - constructor(props) { - super(props); - this.state = { - tooltipShown: false, - }; - } +export const CopyButtonWrapper = ( + props: CopyButtonWrapperProps & { tooltipShown?: boolean }, +): JSX.Element => { + const [tooltipShown, setTooltipShown] = React.useState(false); - render() { - return this.props.children({ renderCopyButton: this.renderCopyButton }); - } - - copy = () => { + const copy = () => { const content = - typeof this.props.data === 'string' - ? this.props.data - : JSON.stringify(this.props.data, null, 2); + typeof props.data === 'string' ? props.data : JSON.stringify(props.data, null, 2); ClipboardService.copyCustom(content); - this.showTooltip(); + showTooltip(); }; - renderCopyButton = () => { + const renderCopyButton = () => { return ( - - + + )} {options => ( (this.node = node!)} + ref={node => setNode(node!)} dangerouslySetInnerHTML={{ - __html: jsonToHTML(this.props.data, options.jsonSampleExpandLevel), + __html: jsonToHTML(props.data, options.jsonSampleExpandLevel), }} /> )} @@ -58,8 +54,8 @@ class Json extends React.PureComponent { ); }; - expandAll = () => { - const elements = this.node.getElementsByClassName('collapsible'); + const expandAll = () => { + const elements = node?.getElementsByClassName('collapsible'); for (const collapsed of Array.prototype.slice.call(elements)) { const parentNode = collapsed.parentNode as Element; parentNode.classList.remove('collapsed'); @@ -67,8 +63,8 @@ class Json extends React.PureComponent { } }; - collapseAll = () => { - const elements = this.node.getElementsByClassName('collapsible'); + const collapseAll = () => { + const elements = node?.getElementsByClassName('collapsible'); // skip first item to avoid collapsing whole object/array const elementsArr = Array.prototype.slice.call(elements, 1); @@ -79,7 +75,7 @@ class Json extends React.PureComponent { } }; - collapseElement = (target: HTMLElement) => { + const collapseElement = (target: HTMLElement) => { let collapsed; if (target.className === 'collapser') { collapsed = target.parentElement!.getElementsByClassName('collapsible')[0]; @@ -93,26 +89,25 @@ class Json extends React.PureComponent { } }; - clickListener = (event: MouseEvent) => { - this.collapseElement(event.target as HTMLElement); - }; + const clickListener = React.useCallback((event: MouseEvent) => { + collapseElement(event.target as HTMLElement); + }, []); - focusListener = (event: KeyboardEvent) => { + const focusListener = React.useCallback((event: KeyboardEvent) => { if (event.key === 'Enter') { - this.collapseElement(event.target as HTMLElement); + collapseElement(event.target as HTMLElement); } - }; + }, []); - componentDidMount() { - this.node!.addEventListener('click', this.clickListener); - this.node!.addEventListener('focus', this.focusListener); - } + React.useEffect(() => { + if (node) { + node?.addEventListener('click', clickListener); + node?.addEventListener('focus', focusListener); + } + }, [clickListener, focusListener, node]); - componentWillUnmount() { - this.node!.removeEventListener('click', this.clickListener); - this.node!.removeEventListener('focus', this.focusListener); - } -} + return {renderInner}; +}; export const JsonViewer = styled(Json)` ${jsonStyles}; diff --git a/src/components/Markdown/AdvancedMarkdown.tsx b/src/components/Markdown/AdvancedMarkdown.tsx index 18bc3f33..dba75e67 100644 --- a/src/components/Markdown/AdvancedMarkdown.tsx +++ b/src/components/Markdown/AdvancedMarkdown.tsx @@ -42,7 +42,8 @@ export class AdvancedMarkdown extends React.Component { { key: idx }, ); } - return ; + const PartComponent = part.component as React.FunctionComponent; + return ; }); } }