askeroo
Version:
A modern CLI prompt library with flow control, history navigation, and conditional prompts
109 lines • 5.73 kB
JavaScript
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
import { useEffect, useMemo } from "react";
import { Text, Box } from "ink";
import { createPrompt } from "../../core/registry.js";
import { completedFieldsStore } from "./completed-fields-store.js";
// Completed fields display plugin
export const completedFields = createPrompt({
type: "completedFields",
component: ({ node, options, events }) => {
// Subscribe to the completed fields store
const store = completedFieldsStore.use();
// Extract completed fields data from the tree
const allFields = useMemo(() => {
if (!store.treeManager) {
return [];
}
const completedFields = [];
store.treeManager.traverseDepthFirst((treeNode) => {
if (treeNode.type === "field" &&
treeNode.completed &&
!treeNode.excludeFromCompleted &&
!treeNode.hideOnCompletion &&
treeNode.value !== undefined) {
const fieldProperties = treeNode.properties || {};
const label = fieldProperties.label ||
fieldProperties.message ||
treeNode.label ||
`${treeNode.fieldType} field`;
const shortLabel = fieldProperties.shortLabel;
// Helper to format values
const formatValue = (value, props) => {
if (Array.isArray(value)) {
if (value.length === 0)
return "None";
if (props?.options &&
Array.isArray(props.options)) {
const selectedLabels = value
.map((val) => {
const option = props.options.find((opt) => opt.value === val);
return option ? option.label : val;
})
.filter(Boolean);
return selectedLabels.join(", ");
}
return value.join(", ");
}
if (typeof value === "boolean") {
// For confirm fields, try to get the label from options
if (props?.options &&
Array.isArray(props.options)) {
const option = props.options.find((opt) => opt.value === value);
return option
? option.label
: value
? "Yes"
: "No";
}
return value ? "Yes" : "No";
}
// Handle falsey values (null, undefined, empty string, 0, false)
if (!value && value !== 0 && value !== false) {
if (value === null)
return "None";
if (value === undefined)
return "Not set";
if (value === "")
return "Empty";
return "None";
}
// For radio fields, get the label from options
if (props?.options && Array.isArray(props.options)) {
const option = props.options.find((opt) => opt.value === value);
if (option) {
return option.label;
}
}
return String(value);
};
completedFields.push({
id: treeNode.id,
label,
shortLabel,
value: treeNode.value,
formattedValue: formatValue(treeNode.value, fieldProperties),
groupLabel: treeNode.parent?.type === "group"
? treeNode.parent.label
: undefined,
meta: fieldProperties.meta,
});
}
});
return completedFields;
}, [store.treeManager, store.revision]);
const completedFieldsList = options.maxFields
? allFields.slice(0, options.maxFields)
: allFields;
// Auto-submit when component becomes active
useEffect(() => {
if (node.state === "active" && events.onSubmit) {
// setTimeout is now baked into onSubmit for auto submissions
events.onSubmit({ type: "auto" });
}
}, [node.state, events.onSubmit]);
if (completedFieldsList.length === 0)
return null;
return (_jsx(Box, { flexDirection: "column", children: completedFieldsList.map((field) => (_jsxs(Box, { gap: 1, children: [_jsx(Box, { width: 18, children: _jsxs(Text, { color: "gray", children: [field.groupLabel && (_jsxs(Text, { color: "white", children: [" ", field.groupLabel, " "] })), field.shortLabel || field.label] }) }), _jsxs(Text, { color: "blue", children: [field.groupLabel && (_jsx(Text, { color: "white", children: " " })), field.formattedValue || field.value] })] }, field.id))) }));
},
});
//# sourceMappingURL=index.js.map