react-command-flow
Version:
A beautiful interactive CLI-style command interface for React apps
1,257 lines (1,244 loc) • 42.5 kB
JavaScript
import React, { useState, useRef, useEffect } from 'react';
function _arrayLikeToArray(r, a) {
(null == a || a > r.length) && (a = r.length);
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
return n;
}
function _arrayWithHoles(r) {
if (Array.isArray(r)) return r;
}
function _arrayWithoutHoles(r) {
if (Array.isArray(r)) return _arrayLikeToArray(r);
}
function asyncGeneratorStep(n, t, e, r, o, a, c) {
try {
var i = n[a](c),
u = i.value;
} catch (n) {
return void e(n);
}
i.done ? t(u) : Promise.resolve(u).then(r, o);
}
function _asyncToGenerator(n) {
return function () {
var t = this,
e = arguments;
return new Promise(function (r, o) {
var a = n.apply(t, e);
function _next(n) {
asyncGeneratorStep(a, r, o, _next, _throw, "next", n);
}
function _throw(n) {
asyncGeneratorStep(a, r, o, _next, _throw, "throw", n);
}
_next(void 0);
});
};
}
function _classCallCheck(a, n) {
if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
}
function _defineProperties(e, r) {
for (var t = 0; t < r.length; t++) {
var o = r[t];
o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o);
}
}
function _createClass(e, r, t) {
return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", {
writable: !1
}), e;
}
function _defineProperty(e, r, t) {
return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
value: t,
enumerable: !0,
configurable: !0,
writable: !0
}) : e[r] = t, e;
}
function _iterableToArray(r) {
if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
}
function _iterableToArrayLimit(r, l) {
var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
if (null != t) {
var e,
n,
i,
u,
a = [],
f = !0,
o = !1;
try {
if (i = (t = t.call(r)).next, 0 === l) {
if (Object(t) !== t) return;
f = !1;
} else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
} catch (r) {
o = !0, n = r;
} finally {
try {
if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
} finally {
if (o) throw n;
}
}
return a;
}
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function ownKeys(e, r) {
var t = Object.keys(e);
if (Object.getOwnPropertySymbols) {
var o = Object.getOwnPropertySymbols(e);
r && (o = o.filter(function (r) {
return Object.getOwnPropertyDescriptor(e, r).enumerable;
})), t.push.apply(t, o);
}
return t;
}
function _objectSpread2(e) {
for (var r = 1; r < arguments.length; r++) {
var t = null != arguments[r] ? arguments[r] : {};
r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {
_defineProperty(e, r, t[r]);
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
});
}
return e;
}
function _regeneratorRuntime() {
_regeneratorRuntime = function () {
return e;
};
var t,
e = {},
r = Object.prototype,
n = r.hasOwnProperty,
o = Object.defineProperty || function (t, e, r) {
t[e] = r.value;
},
i = "function" == typeof Symbol ? Symbol : {},
a = i.iterator || "@@iterator",
c = i.asyncIterator || "@@asyncIterator",
u = i.toStringTag || "@@toStringTag";
function define(t, e, r) {
return Object.defineProperty(t, e, {
value: r,
enumerable: !0,
configurable: !0,
writable: !0
}), t[e];
}
try {
define({}, "");
} catch (t) {
define = function (t, e, r) {
return t[e] = r;
};
}
function wrap(t, e, r, n) {
var i = e && e.prototype instanceof Generator ? e : Generator,
a = Object.create(i.prototype),
c = new Context(n || []);
return o(a, "_invoke", {
value: makeInvokeMethod(t, r, c)
}), a;
}
function tryCatch(t, e, r) {
try {
return {
type: "normal",
arg: t.call(e, r)
};
} catch (t) {
return {
type: "throw",
arg: t
};
}
}
e.wrap = wrap;
var h = "suspendedStart",
l = "suspendedYield",
f = "executing",
s = "completed",
y = {};
function Generator() {}
function GeneratorFunction() {}
function GeneratorFunctionPrototype() {}
var p = {};
define(p, a, function () {
return this;
});
var d = Object.getPrototypeOf,
v = d && d(d(values([])));
v && v !== r && n.call(v, a) && (p = v);
var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p);
function defineIteratorMethods(t) {
["next", "throw", "return"].forEach(function (e) {
define(t, e, function (t) {
return this._invoke(e, t);
});
});
}
function AsyncIterator(t, e) {
function invoke(r, o, i, a) {
var c = tryCatch(t[r], t, o);
if ("throw" !== c.type) {
var u = c.arg,
h = u.value;
return h && "object" == typeof h && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) {
invoke("next", t, i, a);
}, function (t) {
invoke("throw", t, i, a);
}) : e.resolve(h).then(function (t) {
u.value = t, i(u);
}, function (t) {
return invoke("throw", t, i, a);
});
}
a(c.arg);
}
var r;
o(this, "_invoke", {
value: function (t, n) {
function callInvokeWithMethodAndArg() {
return new e(function (e, r) {
invoke(t, n, e, r);
});
}
return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
}
});
}
function makeInvokeMethod(e, r, n) {
var o = h;
return function (i, a) {
if (o === f) throw Error("Generator is already running");
if (o === s) {
if ("throw" === i) throw a;
return {
value: t,
done: !0
};
}
for (n.method = i, n.arg = a;;) {
var c = n.delegate;
if (c) {
var u = maybeInvokeDelegate(c, n);
if (u) {
if (u === y) continue;
return u;
}
}
if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) {
if (o === h) throw o = s, n.arg;
n.dispatchException(n.arg);
} else "return" === n.method && n.abrupt("return", n.arg);
o = f;
var p = tryCatch(e, r, n);
if ("normal" === p.type) {
if (o = n.done ? s : l, p.arg === y) continue;
return {
value: p.arg,
done: n.done
};
}
"throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg);
}
};
}
function maybeInvokeDelegate(e, r) {
var n = r.method,
o = e.iterator[n];
if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y;
var i = tryCatch(o, e.iterator, r.arg);
if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y;
var a = i.arg;
return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y);
}
function pushTryEntry(t) {
var e = {
tryLoc: t[0]
};
1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e);
}
function resetTryEntry(t) {
var e = t.completion || {};
e.type = "normal", delete e.arg, t.completion = e;
}
function Context(t) {
this.tryEntries = [{
tryLoc: "root"
}], t.forEach(pushTryEntry, this), this.reset(!0);
}
function values(e) {
if (e || "" === e) {
var r = e[a];
if (r) return r.call(e);
if ("function" == typeof e.next) return e;
if (!isNaN(e.length)) {
var o = -1,
i = function next() {
for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next;
return next.value = t, next.done = !0, next;
};
return i.next = i;
}
}
throw new TypeError(typeof e + " is not iterable");
}
return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", {
value: GeneratorFunctionPrototype,
configurable: !0
}), o(GeneratorFunctionPrototype, "constructor", {
value: GeneratorFunction,
configurable: !0
}), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) {
var e = "function" == typeof t && t.constructor;
return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name));
}, e.mark = function (t) {
return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t;
}, e.awrap = function (t) {
return {
__await: t
};
}, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () {
return this;
}), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) {
void 0 === i && (i = Promise);
var a = new AsyncIterator(wrap(t, r, n, o), i);
return e.isGeneratorFunction(r) ? a : a.next().then(function (t) {
return t.done ? t.value : a.next();
});
}, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () {
return this;
}), define(g, "toString", function () {
return "[object Generator]";
}), e.keys = function (t) {
var e = Object(t),
r = [];
for (var n in e) r.push(n);
return r.reverse(), function next() {
for (; r.length;) {
var t = r.pop();
if (t in e) return next.value = t, next.done = !1, next;
}
return next.done = !0, next;
};
}, e.values = values, Context.prototype = {
constructor: Context,
reset: function (e) {
if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t);
},
stop: function () {
this.done = !0;
var t = this.tryEntries[0].completion;
if ("throw" === t.type) throw t.arg;
return this.rval;
},
dispatchException: function (e) {
if (this.done) throw e;
var r = this;
function handle(n, o) {
return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o;
}
for (var o = this.tryEntries.length - 1; o >= 0; --o) {
var i = this.tryEntries[o],
a = i.completion;
if ("root" === i.tryLoc) return handle("end");
if (i.tryLoc <= this.prev) {
var c = n.call(i, "catchLoc"),
u = n.call(i, "finallyLoc");
if (c && u) {
if (this.prev < i.catchLoc) return handle(i.catchLoc, !0);
if (this.prev < i.finallyLoc) return handle(i.finallyLoc);
} else if (c) {
if (this.prev < i.catchLoc) return handle(i.catchLoc, !0);
} else {
if (!u) throw Error("try statement without catch or finally");
if (this.prev < i.finallyLoc) return handle(i.finallyLoc);
}
}
}
},
abrupt: function (t, e) {
for (var r = this.tryEntries.length - 1; r >= 0; --r) {
var o = this.tryEntries[r];
if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) {
var i = o;
break;
}
}
i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null);
var a = i ? i.completion : {};
return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a);
},
complete: function (t, e) {
if ("throw" === t.type) throw t.arg;
return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y;
},
finish: function (t) {
for (var e = this.tryEntries.length - 1; e >= 0; --e) {
var r = this.tryEntries[e];
if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y;
}
},
catch: function (t) {
for (var e = this.tryEntries.length - 1; e >= 0; --e) {
var r = this.tryEntries[e];
if (r.tryLoc === t) {
var n = r.completion;
if ("throw" === n.type) {
var o = n.arg;
resetTryEntry(r);
}
return o;
}
}
throw Error("illegal catch attempt");
},
delegateYield: function (e, r, n) {
return this.delegate = {
iterator: values(e),
resultName: r,
nextLoc: n
}, "next" === this.method && (this.arg = t), y;
}
}, e;
}
function _slicedToArray(r, e) {
return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
}
function _toConsumableArray(r) {
return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
}
function _toPrimitive(t, r) {
if ("object" != typeof t || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r || "default");
if ("object" != typeof i) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == typeof i ? i : i + "";
}
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
function _unsupportedIterableToArray(r, a) {
if (r) {
if ("string" == typeof r) return _arrayLikeToArray(r, a);
var t = {}.toString.call(r).slice(8, -1);
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
}
}
var CommandFlowEngine = /*#__PURE__*/function () {
function CommandFlowEngine() {
var commands = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
_classCallCheck(this, CommandFlowEngine);
this.commands = commands;
this.session = null;
}
return _createClass(CommandFlowEngine, [{
key: "startCommand",
value: function () {
var _startCommand = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(commandName) {
var initialData,
command,
output,
firstStep,
prompt,
_args = arguments;
return _regeneratorRuntime().wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
initialData = _args.length > 1 && _args[1] !== undefined ? _args[1] : {};
command = this.commands[commandName];
if (command) {
_context.next = 4;
break;
}
return _context.abrupt("return", {
error: "Unknown command: ".concat(commandName)
});
case 4:
if (!(command.steps.length === 0 && command.onComplete)) {
_context.next = 9;
break;
}
_context.next = 7;
return command.onComplete({}, commandName, this.commands);
case 7:
output = _context.sent;
return _context.abrupt("return", {
output: output
});
case 9:
this.session = {
name: commandName,
stepIndex: 0,
data: initialData,
command: command
};
firstStep = command.steps[0];
_context.next = 13;
return this.resolvePrompt(firstStep);
case 13:
prompt = _context.sent;
return _context.abrupt("return", prompt ? {
prompt: prompt
} : {
error: "Failed to resolve prompt."
});
case 15:
case "end":
return _context.stop();
}
}, _callee, this);
}));
function startCommand(_x) {
return _startCommand.apply(this, arguments);
}
return startCommand;
}()
}, {
key: "isInSession",
value: function isInSession() {
return this.session !== null;
}
}, {
key: "handleInput",
value: function () {
var _handleInput = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(input) {
var _this$session, stepIndex, _this$session$data, data, command, currentStep, validationResult, prompt, redirectTarget, dynamicData, nextStepIndex, nextStep, nextPrompt, output;
return _regeneratorRuntime().wrap(function _callee2$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
if (this.session) {
_context2.next = 2;
break;
}
return _context2.abrupt("return", {
error: "No active command session."
});
case 2:
_this$session = this.session, stepIndex = _this$session.stepIndex, _this$session$data = _this$session.data, data = _this$session$data === void 0 ? {} : _this$session$data, command = _this$session.command; // Ensure data is defined
currentStep = command.steps[stepIndex]; // ✅ 1. Perform validation first
if (!currentStep.validate) {
_context2.next = 13;
break;
}
_context2.next = 7;
return currentStep.validate(input);
case 7:
validationResult = _context2.sent;
if (!(validationResult !== true)) {
_context2.next = 13;
break;
}
_context2.next = 11;
return this.resolvePrompt(currentStep);
case 11:
prompt = _context2.sent;
return _context2.abrupt("return", {
output: validationResult,
prompt: prompt
});
case 13:
if (!currentStep.redirectToCommand) {
_context2.next = 20;
break;
}
redirectTarget = currentStep.redirectToCommand(input, data);
if (!(redirectTarget && this.commands[redirectTarget])) {
_context2.next = 20;
break;
}
this.session = null;
_context2.next = 19;
return this.startCommand(redirectTarget, {
previousInput: input
});
case 19:
return _context2.abrupt("return", _context2.sent);
case 20:
data[currentStep.field] = input;
if (!currentStep.onStep) {
_context2.next = 26;
break;
}
_context2.next = 24;
return currentStep.onStep(input);
case 24:
dynamicData = _context2.sent;
Object.assign(data, dynamicData);
case 26:
nextStepIndex = stepIndex + 1;
if (!(nextStepIndex < command.steps.length)) {
_context2.next = 36;
break;
}
this.session.stepIndex = nextStepIndex;
nextStep = command.steps[nextStepIndex];
_context2.next = 32;
return this.resolvePrompt(nextStep);
case 32:
nextPrompt = _context2.sent;
return _context2.abrupt("return", nextPrompt ? {
prompt: nextPrompt
} : {
error: "Failed to resolve next prompt."
});
case 36:
if (!command.onComplete) {
_context2.next = 42;
break;
}
_context2.next = 39;
return command.onComplete(data || {}, command.name, this.commands);
case 39:
_context2.t0 = _context2.sent;
_context2.next = 43;
break;
case 42:
_context2.t0 = null;
case 43:
output = _context2.t0;
this.session = null; // Move this line after onComplete
return _context2.abrupt("return", {
output: output
});
case 46:
case "end":
return _context2.stop();
}
}, _callee2, this);
}));
function handleInput(_x2) {
return _handleInput.apply(this, arguments);
}
return handleInput;
}()
}, {
key: "resolvePrompt",
value: function () {
var _resolvePrompt = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(step) {
return _regeneratorRuntime().wrap(function _callee3$(_context3) {
while (1) switch (_context3.prev = _context3.next) {
case 0:
if (!(!step || !step.prompt)) {
_context3.next = 2;
break;
}
return _context3.abrupt("return", null);
case 2:
if (!(typeof step.prompt === "function")) {
_context3.next = 6;
break;
}
_context3.next = 5;
return step.prompt();
case 5:
return _context3.abrupt("return", _context3.sent);
case 6:
return _context3.abrupt("return", step.prompt);
case 7:
case "end":
return _context3.stop();
}
}, _callee3);
}));
function resolvePrompt(_x3) {
return _resolvePrompt.apply(this, arguments);
}
return resolvePrompt;
}()
}]);
}();
var useCommandFlow = function useCommandFlow(commands) {
var _useState = useState([]),
_useState2 = _slicedToArray(_useState, 2),
output = _useState2[0],
setOutput = _useState2[1];
var _useState3 = useState(null),
_useState4 = _slicedToArray(_useState3, 2),
currentPrompt = _useState4[0],
setCurrentPrompt = _useState4[1];
var _useState5 = useState(false),
_useState6 = _slicedToArray(_useState5, 2),
isLoading = _useState6[0],
setIsLoading = _useState6[1];
var _useState7 = useState(false),
_useState8 = _slicedToArray(_useState7, 2),
inSession = _useState8[0],
setInSession = _useState8[1];
var engineRef = useRef(new CommandFlowEngine(commands));
var engine = engineRef.current;
useEffect(function () {
setOutput(["✨ Welcome to React Command Flow Terminal ✨", "Type `help` to see available commands."]);
}, []);
var handleUserInput = /*#__PURE__*/function () {
var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(input, onCommandComplete) {
var trimmed, promptEndsWithNewline, result, resolvedOutput, resolvedPrompt, _resolvedPrompt, _resolvedOutput, _result, _resolvedPrompt2, suggestions, _resolvedOutput2;
return _regeneratorRuntime().wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
trimmed = input.trim();
if (!inSession) {
_context.next = 48;
break;
}
if (!["exit", "cancel", "quit"].includes(trimmed.toLowerCase())) {
_context.next = 7;
break;
}
setOutput(function (prev) {
return [].concat(_toConsumableArray(prev), ["> ".concat(trimmed), "❌ Command cancelled."]);
});
setCurrentPrompt(null);
setInSession(false);
return _context.abrupt("return");
case 7:
if (currentPrompt) {
promptEndsWithNewline = currentPrompt.trim().endsWith("\n");
if (promptEndsWithNewline) {
setOutput(function (prev) {
return [].concat(_toConsumableArray(prev), [currentPrompt.trimEnd(), trimmed]);
});
} else {
setOutput(function (prev) {
return [].concat(_toConsumableArray(prev), ["".concat(currentPrompt, " ").concat(trimmed)]);
});
}
} else {
setOutput(function (prev) {
return [].concat(_toConsumableArray(prev), [trimmed]);
});
}
setIsLoading(true);
_context.next = 11;
return engine.handleInput(trimmed);
case 11:
result = _context.sent;
setIsLoading(false);
// Handle validation error
if (!(result.output && result.prompt)) {
_context.next = 23;
break;
}
_context.next = 16;
return Promise.resolve(result.output)["catch"](function () {
return "❌ An error occurred.";
});
case 16:
resolvedOutput = _context.sent;
setOutput(function (prev) {
return [].concat(_toConsumableArray(prev), [resolvedOutput]);
});
_context.next = 20;
return Promise.resolve(result.prompt)["catch"](function () {
return null;
});
case 20:
resolvedPrompt = _context.sent;
setCurrentPrompt(resolvedPrompt);
return _context.abrupt("return");
case 23:
if (!result.prompt) {
_context.next = 29;
break;
}
_context.next = 26;
return Promise.resolve(result.prompt)["catch"](function () {
return null;
});
case 26:
_resolvedPrompt = _context.sent;
setCurrentPrompt(_resolvedPrompt);
return _context.abrupt("return");
case 29:
if (!(result.output === "__CLEAR__")) {
_context.next = 34;
break;
}
setOutput([]);
setCurrentPrompt(null);
setInSession(false);
return _context.abrupt("return");
case 34:
if (!result.output) {
_context.next = 45;
break;
}
setIsLoading(true); // Set loading state before awaiting onComplete
_context.next = 38;
return Promise.resolve(result.output)["catch"](function () {
return "❌ An error occurred.";
});
case 38:
_resolvedOutput = _context.sent;
setIsLoading(false); // Unset loading state after awaiting onComplete
setCurrentPrompt(null);
setInSession(false);
requestAnimationFrame(function () {
setOutput(function (prev) {
return [].concat(_toConsumableArray(prev), [_resolvedOutput]);
});
});
if (onCommandComplete) {
onCommandComplete(); // Use the stored command name
}
return _context.abrupt("return");
case 45:
if (!engine.isInSession()) {
setCurrentPrompt(null);
setInSession(false);
}
_context.next = 79;
break;
case 48:
setOutput(function (prev) {
return [].concat(_toConsumableArray(prev), ["> ".concat(trimmed)]);
});
setIsLoading(true);
_context.next = 52;
return engine.startCommand(trimmed);
case 52:
_result = _context.sent;
setIsLoading(false);
if (!_result.prompt) {
_context.next = 61;
break;
}
_context.next = 57;
return Promise.resolve(_result.prompt)["catch"](function () {
return null;
});
case 57:
_resolvedPrompt2 = _context.sent;
setCurrentPrompt(_resolvedPrompt2);
setInSession(true);
return _context.abrupt("return");
case 61:
if (!(_result.output === "__CLEAR__")) {
_context.next = 66;
break;
}
setOutput([]);
setCurrentPrompt(null);
setInSession(false);
return _context.abrupt("return");
case 66:
if (!_result.error) {
_context.next = 71;
break;
}
suggestions = Object.entries(commands).filter(function (_ref2) {
var _ref3 = _slicedToArray(_ref2, 2);
_ref3[0];
var cmd = _ref3[1];
return !cmd.hidden;
}).map(function (_ref4) {
var _ref5 = _slicedToArray(_ref4, 1),
name = _ref5[0];
return name;
}).filter(function (name) {
return name.includes(trimmed) || name.startsWith(trimmed[0]);
});
if (suggestions.length) {
setOutput(function (prev) {
return [].concat(_toConsumableArray(prev), ["".concat(_result.error), "Did you mean: ".concat(suggestions.join(", "), "?")]);
});
} else {
setOutput(function (prev) {
return [].concat(_toConsumableArray(prev), [_result.error]);
});
}
_context.next = 79;
break;
case 71:
if (!_result.output) {
_context.next = 79;
break;
}
setIsLoading(true); // Set loading state before awaiting onComplete
_context.next = 75;
return Promise.resolve(_result.output)["catch"](function () {
return "❌ An error occurred.";
});
case 75:
_resolvedOutput2 = _context.sent;
setIsLoading(false); // Unset loading state after awaiting onComplete
setOutput(function (prev) {
return [].concat(_toConsumableArray(prev), [_resolvedOutput2]);
});
if (onCommandComplete) {
onCommandComplete();
}
case 79:
case "end":
return _context.stop();
}
}, _callee);
}));
return function handleUserInput(_x, _x2) {
return _ref.apply(this, arguments);
};
}();
return {
output: output,
currentPrompt: currentPrompt,
handleUserInput: handleUserInput,
inSession: inSession,
isLoading: isLoading
};
};
var themes = {
dark: {
backgroundColor: "black",
color: "limegreen",
fontFamily: "monospace",
promptColor: "limegreen",
errorColor: "red",
successColor: "limegreen",
infoColor: "deepskyblue"
},
matrix: {
backgroundColor: "black",
color: "#00FF41",
fontFamily: "monospace",
promptColor: "#00FF41",
errorColor: "#FF3131",
successColor: "#33FF33",
infoColor: "#88FFEE"
},
solarized: {
backgroundColor: "#002b36",
color: "#839496",
fontFamily: "monospace",
promptColor: "#839496",
errorColor: "#dc322f",
successColor: "#859900",
infoColor: "#2aa198"
},
light: {
backgroundColor: "white",
color: "black",
fontFamily: "monospace",
promptColor: "black",
errorColor: "red",
successColor: "green",
infoColor: "blue"
},
dracula: {
backgroundColor: "#282a36",
color: "#f8f8f2",
fontFamily: "monospace",
promptColor: "#f8f8f2",
errorColor: "#ff5555",
successColor: "#50fa7b",
infoColor: "#8be9fd"
},
gruvbox: {
backgroundColor: "#282828",
color: "#ebdbb2",
fontFamily: "monospace",
promptColor: "#ebdbb2",
errorColor: "#fb4934",
successColor: "#b8bb26",
infoColor: "#83a598"
},
nord: {
backgroundColor: "#2E3440",
color: "#D8DEE9",
fontFamily: "monospace",
promptColor: "#D8DEE9",
errorColor: "#BF616A",
successColor: "#A3BE8C",
infoColor: "#88C0D0"
},
ayu: {
backgroundColor: "#0A0E14",
color: "#B3B1AD",
fontFamily: "monospace",
promptColor: "#B3B1AD",
errorColor: "#F07178",
successColor: "#C2D94C",
infoColor: "#59C2FF"
},
palenight: {
backgroundColor: "#292D3E",
color: "#A6ACCD",
fontFamily: "monospace",
promptColor: "#A6ACCD",
errorColor: "#FF5370",
successColor: "#C3E88D",
infoColor: "#89DDFF"
},
monokai: {
backgroundColor: "#272822",
color: "#F8F8F2",
fontFamily: "monospace",
promptColor: "#F8F8F2",
errorColor: "#F92672",
successColor: "#A6E22E",
infoColor: "#66D9EF"
},
oneDark: {
backgroundColor: "#282C34",
color: "#ABB2BF",
fontFamily: "monospace",
promptColor: "#ABB2BF",
errorColor: "#E06C75",
successColor: "#98C379",
infoColor: "#61AFEF"
},
tomorrowNight: {
backgroundColor: "#1D1F21",
color: "#C5C8C6",
fontFamily: "monospace",
promptColor: "#C5C8C6",
errorColor: "#CC6666",
successColor: "#B5BD68",
infoColor: "#81A2BE"
}
};
var CommandLine = function CommandLine(_ref) {
var commands = _ref.commands,
_ref$promptLabel = _ref.promptLabel,
promptLabel = _ref$promptLabel === void 0 ? ">" : _ref$promptLabel,
_ref$theme = _ref.theme,
theme = _ref$theme === void 0 ? "dark" : _ref$theme,
onCommandComplete = _ref.onCommandComplete;
var _useCommandFlow = useCommandFlow(commands),
output = _useCommandFlow.output,
currentPrompt = _useCommandFlow.currentPrompt,
handleUserInput = _useCommandFlow.handleUserInput,
inSession = _useCommandFlow.inSession,
isLoading = _useCommandFlow.isLoading;
var _useState = useState(""),
_useState2 = _slicedToArray(_useState, 2),
input = _useState2[0],
setInput = _useState2[1];
var _useState3 = useState([]),
_useState4 = _slicedToArray(_useState3, 2),
history = _useState4[0],
setHistory = _useState4[1];
var _useState5 = useState(null),
_useState6 = _slicedToArray(_useState5, 2),
historyIndex = _useState6[0],
setHistoryIndex = _useState6[1];
var _useState7 = useState(""),
_useState8 = _slicedToArray(_useState7, 2),
suggestionText = _useState8[0],
setSuggestionText = _useState8[1];
var terminalRef = useRef(null);
var handleSubmit = function handleSubmit(e) {
e.preventDefault();
e.stopPropagation();
if (!input.trim()) return;
// ✅ Add to history only for top-level commands
if (!inSession) {
setHistory(function (prev) {
return [].concat(_toConsumableArray(prev), [input.trim()]);
});
}
handleUserInput(input.trim(), onCommandComplete);
setHistoryIndex(null);
setInput("");
setSuggestionText("");
};
useEffect(function () {
if (terminalRef.current) {
terminalRef.current.scrollTop = terminalRef.current.scrollHeight;
}
}, [output, currentPrompt]);
var terminalTextStyle = {
fontFamily: themes[theme].fontFamily,
fontSize: "1rem",
lineHeight: "1.2rem"
};
var getVisibleCommands = function getVisibleCommands() {
return Object.entries(commands).filter(function (_ref2) {
var _ref3 = _slicedToArray(_ref2, 2);
_ref3[0];
var cmd = _ref3[1];
return !cmd.hidden;
}).map(function (_ref4) {
var _ref5 = _slicedToArray(_ref4, 1),
name = _ref5[0];
return name;
});
};
var handleKeyDown = function handleKeyDown(e) {
if (isLoading || inSession) return; // Disable history navigation when in session
if (e.key === "ArrowUp") {
e.preventDefault();
if (history.length === 0) return;
var newIndex = historyIndex === null ? history.length - 1 : Math.max(0, historyIndex - 1);
setInput(history[newIndex]);
setHistoryIndex(newIndex);
}
if (e.key === "ArrowDown") {
e.preventDefault();
if (history.length === 0 || historyIndex === null) return;
var _newIndex = historyIndex + 1;
if (_newIndex >= history.length) {
setInput("");
setHistoryIndex(null);
} else {
setInput(history[_newIndex]);
setHistoryIndex(_newIndex);
}
}
if (e.key === "Tab") {
e.preventDefault();
var visibleCommands = getVisibleCommands();
var matches = visibleCommands.filter(function (cmd) {
return cmd.startsWith(input.trim());
});
if (matches.length === 1) {
setInput(matches[0]);
setSuggestionText("");
} else if (matches.length > 1) {
var suggestions = "Suggestions: ".concat(matches.join(", "));
setSuggestionText(suggestions);
}
}
};
return /*#__PURE__*/React.createElement("div", {
style: _objectSpread2({
backgroundColor: themes[theme].backgroundColor,
color: themes[theme].color,
padding: "1rem",
borderRadius: "8px",
height: "300px",
overflowY: "auto"
}, terminalTextStyle),
ref: terminalRef
}, output.map(function (line, idx) {
if (_typeof(line) === "object") {
if (typeof line.then === "function") {
// Handle Promise
console.warn("[DEV WARNING] React tried to render a Promise at output index ".concat(idx, ". Did you forget to await onComplete?"));
return null;
} else {
// Handle object
line = JSON.stringify(line);
}
}
if (typeof line === "string" || typeof line === "number" || /*#__PURE__*/React.isValidElement(line) || Array.isArray(line)) {
return /*#__PURE__*/React.createElement("div", {
key: idx,
style: _objectSpread2({
whiteSpace: "pre-wrap"
}, terminalTextStyle)
}, line);
}
return null;
}), isLoading ? /*#__PURE__*/React.createElement("div", {
style: {
fontStyle: "italic"
}
}, "\u231B Please wait...") : currentPrompt ? function () {
var promptLines = currentPrompt.split("\n");
var lastPromptLine = promptLines.pop();
var multilinePart = promptLines.join("\n");
return /*#__PURE__*/React.createElement(React.Fragment, null, multilinePart && /*#__PURE__*/React.createElement("div", {
style: _objectSpread2({
whiteSpace: "pre-wrap"
}, terminalTextStyle)
}, multilinePart), /*#__PURE__*/React.createElement("form", {
onSubmit: handleSubmit,
autoComplete: "off",
style: {
display: "flex",
marginTop: "0px"
}
}, /*#__PURE__*/React.createElement("span", {
style: _objectSpread2({
marginRight: "0.5rem",
whiteSpace: "pre-wrap",
color: themes[theme].promptColor
}, terminalTextStyle)
}, lastPromptLine), /*#__PURE__*/React.createElement("input", {
type: "text",
style: _objectSpread2({
backgroundColor: themes[theme].backgroundColor,
color: themes[theme].color,
border: "none",
outline: "none",
flex: 1,
padding: 0,
margin: 0
}, terminalTextStyle),
value: input,
onChange: function onChange(e) {
return setInput(e.target.value);
},
onKeyDown: handleKeyDown,
autoFocus: true,
disabled: isLoading
})), suggestionText && /*#__PURE__*/React.createElement("div", {
style: _objectSpread2({
whiteSpace: "pre-wrap",
marginTop: "0.2rem"
}, terminalTextStyle)
}, suggestionText));
}() : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("form", {
onSubmit: handleSubmit,
autoComplete: "off",
style: {
display: "flex",
marginTop: "0px"
}
}, /*#__PURE__*/React.createElement("span", {
style: _objectSpread2({
marginRight: "0.5rem",
color: themes[theme].promptColor
}, terminalTextStyle)
}, promptLabel), /*#__PURE__*/React.createElement("input", {
type: "text",
style: _objectSpread2({
backgroundColor: themes[theme].backgroundColor,
color: themes[theme].color,
border: "none",
outline: "none",
flex: 1,
padding: 0,
margin: 0
}, terminalTextStyle),
value: input,
onChange: function onChange(e) {
return setInput(e.target.value);
},
onKeyDown: handleKeyDown,
autoFocus: true,
disabled: isLoading
})), suggestionText && /*#__PURE__*/React.createElement("div", {
style: _objectSpread2({
whiteSpace: "pre-wrap",
marginTop: "0.2rem"
}, terminalTextStyle)
}, suggestionText)));
};
export { CommandLine, useCommandFlow };
//# sourceMappingURL=index.js.map