@shopify/cli-kit
Version:
A set of utilities, interfaces, and models that are common across all the platform features
71 lines • 4 kB
JavaScript
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