UNPKG

@shopify/cli-kit

Version:

A set of utilities, interfaces, and models that are common across all the platform features

71 lines 4 kB
import { InfoMessage } from './InfoMessage.js'; import { InfoTable } from './InfoTable.js'; import { TokenizedText } from '../TokenizedText.js'; import { messageWithPunctuation } from '../../utilities.js'; import useAbortSignal from '../../hooks/use-abort-signal.js'; import { PromptState } from '../../hooks/use-prompt.js'; import React, { cloneElement, useCallback, useLayoutEffect, useState } from 'react'; import { Box, measureElement, Text, useStdout } from 'ink'; import figures from 'figures'; const PromptLayout = ({ message, infoTable, abortSignal, infoMessage, header, state, input, submittedAnswerLabel, }) => { const { stdout } = useStdout(); const [wrapperHeight, setWrapperHeight] = useState(0); const [promptAreaHeight, setPromptAreaHeight] = useState(0); const [inputFixedAreaHeight, setInputFixedAreaHeight] = useState(0); const currentAvailableLines = stdout.rows - promptAreaHeight - inputFixedAreaHeight; const [availableLines, setAvailableLines] = useState(currentAvailableLines); const wrapperRef = useCallback((node) => { if (node !== null) { const { height } = measureElement(node); if (wrapperHeight !== height) { setWrapperHeight(height); } } }, [wrapperHeight]); const promptAreaRef = useCallback((node) => { if (node !== null) { const { height } = measureElement(node); setPromptAreaHeight(height); } }, []); const inputFixedAreaRef = useCallback((node) => { if (node !== null) { const { height } = measureElement(node); // + 3 accounts for the margins inside the input elements and the last empty line of the terminal setInputFixedAreaHeight(height + 3); } }, []); const inputComponent = cloneElement(input, { availableLines, inputFixedAreaRef }); useLayoutEffect(() => { function onResize() { const newAvailableLines = stdout.rows - promptAreaHeight - inputFixedAreaHeight; if (newAvailableLines !== availableLines) { setAvailableLines(newAvailableLines); } } onResize(); stdout.on('resize', onResize); return () => { stdout.off('resize', onResize); }; }, [wrapperHeight, promptAreaHeight, stdout, availableLines, inputFixedAreaHeight]); const { isAborted } = useAbortSignal(abortSignal); // Object.keys on an array returns the indices as strings const showInfoTable = infoTable && Object.keys(infoTable).length > 0; return isAborted ? null : (React.createElement(Box, { flexDirection: "column", marginBottom: 1, ref: wrapperRef }, React.createElement(Box, { ref: promptAreaRef, flexDirection: "column" }, React.createElement(Box, null, React.createElement(Box, { marginRight: 2 }, React.createElement(Text, null, "?")), React.createElement(TokenizedText, { item: messageWithPunctuation(message) }), header), (showInfoTable || infoMessage) && state !== PromptState.Submitted ? (React.createElement(Box, { marginTop: 1, marginLeft: 3, paddingLeft: 2, borderStyle: "bold", borderLeft: true, borderRight: false, borderTop: false, borderBottom: false, flexDirection: "column", gap: 1 }, infoMessage ? React.createElement(InfoMessage, { message: infoMessage }) : null, showInfoTable ? React.createElement(InfoTable, { table: infoTable }) : null)) : null), state === PromptState.Submitted && submittedAnswerLabel ? (React.createElement(Box, null, React.createElement(Box, { width: 3 }, React.createElement(Text, { color: "cyan" }, figures.tick)), React.createElement(Text, { color: "cyan" }, submittedAnswerLabel))) : (React.createElement(Box, { marginTop: 1 }, inputComponent)))); }; export { PromptLayout }; //# sourceMappingURL=PromptLayout.js.map