Files
swagger-ui/src/core/components/highlight-code.jsx
Vladimir Gorej 46b4e5cf3f fix(highlight-code): handle mousewheel events properly
SyntaxHighlighter component doesn't support ref. We had
to use different approach to finds it's DOM Node using
ref of the root Node of the render tree for HighlightCode
component.

Refs #7497
2021-11-03 09:49:50 +01:00

91 lines
2.9 KiB
JavaScript

import React, { useRef, useEffect } from "react"
import PropTypes from "prop-types"
import cx from "classnames"
import {SyntaxHighlighter, getStyle} from "core/syntax-highlighting"
import get from "lodash/get"
import isFunction from "lodash/isFunction"
import saveAs from "js-file-download"
import { CopyToClipboard } from "react-copy-to-clipboard"
const HighlightCode = ({value, fileName, className, downloadable, getConfigs, canCopy, language}) => {
const config = isFunction(getConfigs) ? getConfigs() : null
const canSyntaxHighlight = get(config, "syntaxHighlight.activated", true)
const highlighterStyle = getStyle(get(config, "syntaxHighlight.theme", "agate"))
const rootRef = useRef(null)
useEffect(() => {
const childNodes = Array
.from(rootRef.current.childNodes)
.filter(node => !!node.nodeType && node.classList.contains("microlight"))
// eslint-disable-next-line no-use-before-define
childNodes.forEach(node => node.addEventListener("mousewheel", handlePreventYScrollingBeyondElement, { passive: false }))
return () => {
// eslint-disable-next-line no-use-before-define
childNodes.forEach(node => node.removeEventListener("mousewheel", handlePreventYScrollingBeyondElement))
}
}, [value, className, language])
const handleDownload = () => {
saveAs(value, fileName)
}
const handlePreventYScrollingBeyondElement = (e) => {
const { target, deltaY } = e
const { scrollHeight: contentHeight, offsetHeight: visibleHeight, scrollTop } = target
const scrollOffset = visibleHeight + scrollTop
const isElementScrollable = contentHeight > visibleHeight
const isScrollingPastTop = scrollTop === 0 && deltaY < 0
const isScrollingPastBottom = scrollOffset >= contentHeight && deltaY > 0
if (isElementScrollable && (isScrollingPastTop || isScrollingPastBottom)) {
e.preventDefault()
}
}
return (
<div className="highlight-code" ref={rootRef}>
{!downloadable ? null :
<div className="download-contents" onClick={handleDownload}>
Download
</div>
}
{canCopy && (
<div className="copy-to-clipboard">
<CopyToClipboard text={value}><button/></CopyToClipboard>
</div>
)}
{canSyntaxHighlight
? <SyntaxHighlighter
language={language}
className={cx(className, "microlight")}
style={highlighterStyle}
>
{value}
</SyntaxHighlighter>
: <pre className={cx(className + "microlight")}>{value}</pre>
}
</div>
)
}
HighlightCode.propTypes = {
value: PropTypes.string.isRequired,
getConfigs: PropTypes.func.isRequired,
className: PropTypes.string,
downloadable: PropTypes.bool,
fileName: PropTypes.string,
language: PropTypes.string,
canCopy: PropTypes.bool
}
HighlightCode.defaultProps = {
fileName: "response.txt"
}
export default HighlightCode