UNPKG

@primer/react

Version:

An implementation of GitHub's Primer Design System using React

76 lines (71 loc) 2.77 kB
import React__default, { useRef, useState, useEffect, useCallback } from 'react'; import { useLinkInterception } from './_useLinkInterception.js'; import { useListInteraction } from './_useListInteraction.js'; import Box from '../../Box/Box.js'; import Spinner from '../../Spinner/Spinner.js'; const createRenderedContainer = html => { const div = document.createElement('div'); div.innerHTML = html; return div; }; const MarkdownViewer = ({ dangerousRenderedHTML, loading = false, markdownValue = '', onChange: externalOnChange, disabled = false, onLinkClick, openLinksInNewTab = false }) => { const outputContainerRef = useRef(null); // Render the HTML into an internal container element so we can modify it before it becomes visible. // Using `unsafeInnerHTML` would require an effect to run after rendering which would cause flicker const [htmlContainer, setHtmlContainer] = useState(() => createRenderedContainer(dangerousRenderedHTML.__html)); useEffect(() => setHtmlContainer(createRenderedContainer(dangerousRenderedHTML.__html)), [dangerousRenderedHTML.__html]); const onChange = useCallback(async value => { try { await (externalOnChange === null || externalOnChange === void 0 ? void 0 : externalOnChange(value)); } catch (error) { setHtmlContainer(createRenderedContainer(dangerousRenderedHTML.__html)); } }, [externalOnChange, dangerousRenderedHTML.__html]); useListInteraction({ onChange, disabled: disabled || !externalOnChange, htmlContainer, markdownValue }); useLinkInterception({ htmlContainer, onLinkClick, openLinksInNewTab }); // If we were to inject the `...htmlContainer.children` instead of the container element itself, // those children elements would be moved from the `htmlContainer` to the `outputContainer`. Then if // other effects use `htmlContainer.querySelectorAll`, they wouldn't find any elements to affect useEffect(() => { var _outputContainerRef$c; return (_outputContainerRef$c = outputContainerRef.current) === null || _outputContainerRef$c === void 0 ? void 0 : _outputContainerRef$c.replaceChildren(htmlContainer); }, [htmlContainer]); return loading ? /*#__PURE__*/React__default.createElement(Box, { sx: { display: 'flex', justifyContent: 'space-around', p: 2 } }, /*#__PURE__*/React__default.createElement(Spinner, { "aria-label": "Loading content..." })) : /*#__PURE__*/React__default.createElement(Box, { ref: outputContainerRef, className: "markdown-body", sx: { fontSize: 1, maxWidth: '100%', '& > div > :last-child': { mb: 0 } } }); }; var MarkdownViewer$1 = MarkdownViewer; export { MarkdownViewer$1 as default };