import React, { useState, useEffect } from 'react' import cx from 'classnames' import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter' import { vs, vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism' import { usePlaygroundContext } from 'components/context/PlaygroundContext' import { LoadingIndicator } from './LoadingIndicator' import { ActionBar } from './ActionBar' import { CodeBlockRef, PlaygroundArticleT } from '../types' import { useTheme } from '@primer/react' const getNormalizedHighlight = ( highlight: Exclude ): Array<[number, number]> => { if (typeof highlight === 'number') { return [[highlight, highlight]] } else if (typeof highlight[0] === 'number') { return [highlight as [number, number]] } else { return highlight as Array<[number, number]> } } interface Props { article: PlaygroundArticleT } export const Editor: React.FC = ({ article }) => { const theme = useTheme() const [isEditorReady, setIsEditorReady] = useState(false) const [selectedFileIndex, setSelectedFileIndex] = useState(0) const { activeSectionIndex } = usePlaygroundContext() const normalizedHighlight = getNormalizedHighlight( article.contentBlocks[activeSectionIndex]?.codeBlock.highlight || [] ) useEffect(() => { // Some buffer to load the theme, otherwise it flashes the light theme momentarily const timeout = setTimeout(() => { setIsEditorReady(true) }, 250) return () => { clearTimeout(timeout) } }, []) useEffect(() => { if (selectedFileIndex !== 0) { setSelectedFileIndex(0) } }, [activeSectionIndex]) // find the set of files we want displayed in the editor const codeBlockId = article.contentBlocks[activeSectionIndex].codeBlock.id let editorFiles = article.codeBlocks[codeBlockId] if (!Array.isArray(editorFiles)) { editorFiles = [editorFiles] } let activeFile = editorFiles[selectedFileIndex] if (!activeFile) { activeFile = editorFiles[0] } return (
{editorFiles.map((file, i) => { return ( ) })}
{isEditorReady ? ( { let className = '' for (const highlight of normalizedHighlight) { if (lineNumber >= highlight[0] && lineNumber <= highlight[1]) { className = 'color-bg-accent' } } return { style: { display: 'block' }, class: className } }} lineNumberStyle={{ minWidth: '3.25em' }} > {activeFile.code} ) : ( )}
) }