UNPKG

@redocly/theme

Version:

Shared UI components lib

94 lines 4.58 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useCodePanel = useCodePanel; const react_1 = require("react"); const contexts_1 = require("../../../core/contexts"); const hooks_1 = require("../../../core/hooks"); const ACTIVE_FILE_MOCK = { content: [], path: '', basename: '', metadata: {}, language: '', }; function useCodePanel(files) { const { activeStep } = (0, react_1.useContext)(contexts_1.CodeWalkthroughStepsContext); const { areConditionsMet, populateInputsWithValue } = (0, react_1.useContext)(contexts_1.CodeWalkthroughControlsStateContext); const { useCodeHighlight } = (0, hooks_1.useThemeHooks)(); const { highlight } = useCodeHighlight(); const findFileIndexByName = (0, react_1.useCallback)((name) => { return files.findIndex((file) => file.path === name); }, [files]); const findFileIndexByStepId = (0, react_1.useCallback)((id) => files.findIndex((file) => file.metadata.steps.includes(id)), [files]); const activeStepFileIndex = activeStep ? findFileIndexByStepId(activeStep) : 0; const initialActiveFileIndex = activeStepFileIndex !== -1 ? activeStepFileIndex : 0; const [activeFileIndex, setActiveFileIndex] = (0, react_1.useState)(initialActiveFileIndex); (0, react_1.useEffect)(() => { setActiveFileIndex(initialActiveFileIndex); }, [initialActiveFileIndex, activeStep, files]); const handleTabSwitch = (0, react_1.useCallback)((name) => { const index = findFileIndexByName(name); if (index !== -1) { setActiveFileIndex(index); } }, [findFileIndexByName]); const activeFile = files[activeFileIndex] || // Fallback to default. Needed when switching from language with more files to a language with less files files[initialActiveFileIndex] || // Final fallback for dev mode when no files were added yet ACTIVE_FILE_MOCK; const highlightedCode = (0, react_1.useMemo)(() => { const { highlightedLines, code, isWholeFileSelected } = getRenderableCode(activeFile, activeStep, areConditionsMet, populateInputsWithValue); return highlight(code, activeFile.language, { withLineNumbers: true, // Shiki transformerMetaHighlight meta to highlight lines // If the whole file is selected for a step, do not apply highlighting highlight: isWholeFileSelected ? '' : `{${Array.from(highlightedLines).join(',')}}`, customTransformer: { // Add greyed-out class to lines that are not highlighted line(hast, number) { if (!highlightedLines.has(number)) { this.addClassToHast(hast, 'greyed-out'); } }, }, }); }, [activeFile, activeStep, highlight, areConditionsMet, populateInputsWithValue]); return { activeFile, handleTabSwitch, highlightedCode }; } function getRenderableCode(activeFile, activeStep, areConditionsMet, populateInputsWithValue) { const codeLines = activeFile.content.flatMap((node) => getCodeLinesFromNode(node, activeStep, areConditionsMet, populateInputsWithValue)); const codeLinesContent = []; const highlightedLines = new Set(); codeLines.forEach(({ lineContent, highlighted }, idx) => { codeLinesContent.push(lineContent); if (highlighted) { highlightedLines.add(idx + 1); } }); return { highlightedLines, code: codeLinesContent.join('\n'), isWholeFileSelected: highlightedLines.size === codeLinesContent.length, }; } /** * Convert code node to code line objects with content to render and their highlighted status */ function getCodeLinesFromNode(node, activeStep, areConditionsMet, populateInputsWithValue, parentHighlighted = false) { if (typeof node === 'string') { const replacedNode = populateInputsWithValue(node); return [{ lineContent: replacedNode, highlighted: parentHighlighted }]; } else { const shouldRenderChunk = areConditionsMet(node.condition); const isHighlighted = parentHighlighted || (activeStep != null && node.condition.steps.length > 0 && node.condition.steps.includes(activeStep)); return shouldRenderChunk ? node.children.flatMap((child) => getCodeLinesFromNode(child, activeStep, areConditionsMet, populateInputsWithValue, isHighlighted)) : []; } } //# sourceMappingURL=use-code-panel.js.map