askeroo
Version:
A modern CLI prompt library with flow control, history navigation, and conditional prompts
123 lines • 4.72 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import { useMemo } from "react";
import { globalRegistry } from "../core/registry.js";
/**
* Wrapper component that transforms flat props into structured format.
*
* This wrapper transforms flat props into a structured format with:
* - `options`: User-provided configuration (label, shortLabel, initialValue, etc.)
* - `node`: Library flow node properties (state, flow, isFirstInGroup, etc.)
* - `events`: Event handlers (onSubmit, onBack, onHintChange, etc.)
*
* Note: Auto-submit behavior is now controlled within each plugin component.
* Components submit with consistent format: { type: "auto" | "skip" | "programmatic", value?: any }
* Regular values (non-objects or objects without type property) are treated as manual submissions
*/
export function PluginWrapper({ pluginType, promptId, ...props }) {
const PluginComponent = globalRegistry.getComponent(pluginType);
if (!PluginComponent) {
return null;
}
// Memoize the wrapped onSubmit to prevent unnecessary re-renders
const wrappedOnSubmit = useMemo(() => {
if (!props.onSubmit)
return undefined;
const originalOnSubmit = props.onSubmit;
const capturedPromptId = promptId;
return (value) => {
// Check if this is an auto/skip/programmatic submission
const isSpecialSubmission = typeof value === "object" &&
value !== null &&
"type" in value &&
(value.type === "auto" ||
value.type === "skip" ||
value.type === "programmatic");
if (isSpecialSubmission) {
// Get delay from submission object, default to 0ms
const delay = typeof value.delay === "number" ? value.delay : 0;
// Apply setTimeout with the specified delay
// Include the captured prompt ID so handleSubmit knows which prompt this is for
setTimeout(() => {
originalOnSubmit({
...value,
__promptId: capturedPromptId,
});
}, delay);
}
else {
// Regular submission - call immediately
originalOnSubmit(value);
}
};
}, [props.onSubmit, promptId]);
// Memoize the wrapped onComplete to automatically use the correct promptId
const wrappedOnComplete = useMemo(() => {
if (!props.onComplete)
return undefined;
const originalOnComplete = props.onComplete;
const capturedPromptId = promptId;
return () => {
// Call onComplete with the node's promptId, not whatever the component passes
originalOnComplete(capturedPromptId);
};
}, [props.onComplete, promptId]);
// Transform flat props into structured format
const transformedProps = transformPropsToStructure(props, wrappedOnSubmit, wrappedOnComplete);
// Handle user's onSubmit callback separately
if (props.userOnSubmit) {
transformedProps.options.onSubmit = props.userOnSubmit;
}
// Render plugin component directly
return _jsx(PluginComponent, { ...transformedProps });
}
/**
* Transform flat props into structured format with node, options, and events
*/
function transformPropsToStructure(props, wrappedOnSubmit, wrappedOnComplete) {
// Define known node properties
const nodeProps = [
"state",
"flow",
"isFirstInGroup",
"isLastInGroup",
"isFirstRootPrompt",
"allowBack",
"completedValue",
"enableArrowNavigation",
"depth",
"children",
];
// Define known event handlers
const eventProps = [
"onBack",
"onComplete",
"onHintChange",
"onValidate",
"onNavigate",
];
// Separate props into their categories
const node = {};
const events = {};
const options = {};
for (const [key, value] of Object.entries(props)) {
if (nodeProps.includes(key)) {
node[key] = value;
}
else if (eventProps.includes(key)) {
events[key] = value;
}
else {
options[key] = value;
}
}
// Use the wrapped callbacks if provided (they're already memoized)
// Note: wrappedOnSubmit is the internal framework callback, not the user's onSubmit
if (wrappedOnSubmit) {
events.onSubmit = wrappedOnSubmit;
}
if (wrappedOnComplete) {
events.onComplete = wrappedOnComplete;
}
return { node, options, events };
}
//# sourceMappingURL=PluginWrapper.js.map